/*
 * Copyright 2009 Google Inc.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package com.google.gwt.dev.javac.asm;

import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.typeinfo.JAbstractMethod;
import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.core.ext.typeinfo.JGenericType;
import com.google.gwt.core.ext.typeinfo.JMethod;
import com.google.gwt.core.ext.typeinfo.JPackage;
import com.google.gwt.core.ext.typeinfo.JRealClassType;
import com.google.gwt.core.ext.typeinfo.JType;
import com.google.gwt.core.ext.typeinfo.JTypeParameter;
import com.google.gwt.core.ext.typeinfo.TypeOracle;
import com.google.gwt.dev.asm.Opcodes;
import com.google.gwt.dev.asm.Type;
import com.google.gwt.dev.asm.signature.SignatureReader;
import com.google.gwt.dev.javac.MethodArgNamesLookup;
import com.google.gwt.dev.javac.Resolver;
import com.google.gwt.dev.javac.TypeOracleMediator;
import com.google.gwt.dev.javac.TypeOracleTestingUtils;
import com.google.gwt.dev.javac.TypeParameterLookup;
import com.google.gwt.dev.javac.asm.CollectClassData.ClassType;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.TypeVariable;
import java.util.Collections;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;

/**
 * Tests for {@link ResolveClassSignature} and {@link ResolveMethodSignature}.
 */
public class ResolveGenericsTest extends AsmTestCase {

  public static class FailErrorTreeLogger extends TreeLogger {
    @Override
    public TreeLogger branch(com.google.gwt.core.ext.TreeLogger.Type type,
        String msg, Throwable caught, HelpInfo helpInfo) {
      if (type == TreeLogger.ERROR) {
        fail(msg);
      }
      return this;
    }

    @Override
    public boolean isLoggable(com.google.gwt.core.ext.TreeLogger.Type type) {
      return true;
    }

    @Override
    public void log(com.google.gwt.core.ext.TreeLogger.Type type, String msg,
        Throwable caught, HelpInfo helpInfo) {
      if (type == TreeLogger.ERROR) {
        fail(msg);
      }
    }
  }

  private class MockResolver implements Resolver {
    private final Resolver delegate;

    public MockResolver(Resolver resolver) {
      this.delegate = resolver;
    }

    public void addImplementedInterface(JRealClassType type, JClassType intf) {
      delegate.addImplementedInterface(type, intf);
    }

    public void addThrows(JAbstractMethod method, JType exception) {
      delegate.addThrows(method, exception);
    }

    public Map<String, JRealClassType> getBinaryMapper() {
      return delegate.getBinaryMapper();
    }

    public TypeOracle getTypeOracle() {
      return delegate.getTypeOracle();
    }

    public JMethod newMethod(JClassType type, String name,
        Map<Class<? extends Annotation>, Annotation> declaredAnnotations,
        JTypeParameter[] typeParams) {
      return delegate.newMethod(type, name, declaredAnnotations, typeParams);
    }

    public void newParameter(JAbstractMethod method, JType argType,
        String argName,
        Map<Class<? extends Annotation>, Annotation> declaredAnnotations,
        boolean argNamesAreReal) {
      delegate.newParameter(method, argType, argName, declaredAnnotations,
          argNamesAreReal);
    }

    public JRealClassType newRealClassType(JPackage pkg,
        String enclosingTypeName, boolean isLocalType, String className,
        boolean isIntf) {
      return delegate.newRealClassType(pkg, enclosingTypeName, isLocalType,
          className, isIntf);
    }

    public boolean resolveAnnotation(TreeLogger logger,
        CollectAnnotationData annotVisitor,
        Map<Class<? extends Annotation>, Annotation> declaredAnnotations) {
      return true;
    }

    public boolean resolveAnnotations(TreeLogger logger,
        List<CollectAnnotationData> annotations,
        Map<Class<? extends Annotation>, Annotation> declaredAnnotations) {
      return true;
    }

    public boolean resolveClass(TreeLogger logger, JRealClassType type) {
      return true;
    }

    public void setReturnType(JAbstractMethod method, JType returnType) {
      delegate.setReturnType(method, returnType);
    }

    public void setSuperClass(JRealClassType type, JClassType superType) {
      delegate.setSuperClass(type, superType);
    }
  }

  private static final TreeLogger failTreeLogger = new FailErrorTreeLogger();

  private static final String OUTER_CLASS_SIG = "<H:Lcom/google/gwt/dev/javac/asm/TestHandler;>Ljava/lang/Object;";
  private static final String OUTER_METHOD_SIG = "(TH;)V";

  private static final String OUTER1_CLASS_SIG = "<V:Ljava/lang/Object;>Lcom/google/gwt/dev/javac/asm/TestOuter0<"
      + "Lcom/google/gwt/dev/javac/asm/TestHandler1<TV;>;>;";
  private static final String OUTER1_METHOD_SIG = "(Lcom/google/gwt/dev/javac/asm/TestHandler1<TV;>;)V";

  private static final String OUTER2_CLASS_SIG = "Lcom/google/gwt/dev/javac/asm/TestOuter1<Ljava/lang/String;>;";
  private static final String OUTER2_METHOD_SIG = "(Lcom/google/gwt/dev/javac/asm/TestHandler1<Ljava/lang/String;>;)V";

  private final TypeOracleMediator mediator;

  private final TypeOracle oracle;

  private final Map<JMethod, Method> reflectionMethods = new IdentityHashMap<JMethod, Method>();

  private final MockResolver resolver;

  @SuppressWarnings("unused")
  private JRealClassType testHandler;
  @SuppressWarnings("unused")
  private JRealClassType testHandler1;

  private JRealClassType testOuter0;
  private JMethod testOuter0dispatch;
  private JRealClassType testOuter1;

  private JMethod testOuter1dispatch;
  private JRealClassType testOuter2;
  private JMethod testOuter2dispatch;

  @SuppressWarnings("unused")
  private JRealClassType testType;

  public ResolveGenericsTest() {
    mediator = TypeOracleTestingUtils.buildStandardMediatorWith(failTreeLogger);
    resolver = new MockResolver(mediator.getResolver());
    oracle = mediator.getTypeOracle();
    createUnresolvedClass(String.class, null);
    testHandler = createUnresolvedClass(TestHandler.class, null);
    testHandler1 = createUnresolvedClass(TestHandler1.class, null);
    testOuter0 = createUnresolvedClass(TestOuter0.class, null);
    testType = createUnresolvedClass(TestOuter0.Type.class, testOuter0);
    testOuter1 = createUnresolvedClass(TestOuter1.class, null);
    testOuter2 = createUnresolvedClass(TestOuter2.class, null);
    testOuter0dispatch = createUnresolvedMethod(testOuter0, TestOuter0.class,
        "dispatch", TestHandler.class);
    testOuter1dispatch = createUnresolvedMethod(testOuter1, TestOuter1.class,
        "dispatch", TestHandler.class);
    testOuter2dispatch = createUnresolvedMethod(testOuter2, TestOuter2.class,
        "dispatch", TestHandler.class);
    for (JClassType type : oracle.getTypes()) {
      if (type instanceof JRealClassType) {
        mediator.getBinaryMapper().put(
            type.getQualifiedBinaryName().replace('.', '/'),
            (JRealClassType) type);
      }
    }
  }

  public void testOuter0Class() {
    resolveClassSignature(testOuter0, OUTER_CLASS_SIG);
    assertNotNull(testOuter0.getSuperclass());
    // TODO(jat): additional checks?
  }

  public void testOuter0Method() {
    resolveMethodSignature(testOuter0dispatch, OUTER_METHOD_SIG);
    // TODO(jat): meaningful tests besides no errors?
  }

  public void testOuter1Class() {
    resolveClassSignature(testOuter1, OUTER1_CLASS_SIG);
    JClassType superClass = testOuter1.getSuperclass();
    assertNotNull(superClass);
    assertNotNull(superClass.isParameterized());
    // TODO(jat): additional checks?
  }

  public void testOuter1Method() {
    resolveMethodSignature(testOuter1dispatch, OUTER1_METHOD_SIG);
    // TODO(jat): meaningful tests besides no errors?
  }

  public void testOuter2Class() {
    resolveClassSignature(testOuter2, OUTER2_CLASS_SIG);
    JClassType superClass = testOuter2.getSuperclass();
    assertNotNull(superClass);
    assertNotNull(superClass.isParameterized());
    // TODO(jat): additional checks?
  }

  public void testOuter2Method() {
    resolveMethodSignature(testOuter2dispatch, OUTER2_METHOD_SIG);
    // TODO(jat): meaningful tests besides no errors?
  }

  private JTypeParameter[] createTypeParams(TypeVariable<?>[] typeParams) {
    int n = typeParams.length;
    JTypeParameter[] params = new JTypeParameter[n];
    for (int i = 0; i < n; ++i) {
      params[i] = new JTypeParameter(typeParams[i].getName(), i);
    }
    return params;
  }

  private JRealClassType createUnresolvedClass(Class<?> clazz,
      JRealClassType enclosingType) {
    String pkgName = clazz.getPackage().getName();
    JPackage pkg = oracle.getOrCreatePackage(pkgName);
    TypeVariable<?>[] typeParams = clazz.getTypeParameters();
    JRealClassType type;
    int n = typeParams.length;
    String enclosingTypeName = null;
    if (enclosingType != null) {
      enclosingTypeName = enclosingType.getName();
    }
    if (n == 0) {
      type = resolver.newRealClassType(pkg, enclosingTypeName, false,
          clazz.getSimpleName(), clazz.isInterface());
    } else {
      JTypeParameter[] params = createTypeParams(typeParams);
      type = new JGenericType(oracle, pkg, enclosingTypeName, clazz.getSimpleName(),
          clazz.isInterface(), params);
    }
    return type;
  }

  private JMethod createUnresolvedMethod(JClassType type, Class<?> clazz,
      String methodName, Class<?>... paramTypes) {
    Method method = null;
    try {
      method = clazz.getMethod(methodName, paramTypes);
    } catch (SecurityException e) {
      fail("Exception " + e + " creating method " + methodName + " on " + clazz);
    } catch (NoSuchMethodException e) {
      fail("Exception " + e + " creating method " + methodName + " on " + clazz);
    }
    JTypeParameter[] typeParams = createTypeParams(method.getTypeParameters());
    Map<Class<? extends Annotation>, Annotation> emptyMap = Collections.emptyMap();
    JMethod result = resolver.newMethod(type, methodName, emptyMap, typeParams);
    reflectionMethods.put(result, method);
    return result;
  }

  private void resolveClassSignature(JRealClassType type, String signature) {
    Map<String, JRealClassType> binaryMapper = resolver.getBinaryMapper();
    TypeParameterLookup lookup = new TypeParameterLookup();
    lookup.pushEnclosingScopes(type);
    ResolveClassSignature classResolver = new ResolveClassSignature(resolver,
        binaryMapper, failTreeLogger, type, lookup);
    new SignatureReader(signature).accept(classResolver);
    classResolver.finish();
  }

  private void resolveMethodSignature(JMethod method, String signature) {
    TypeParameterLookup lookup = new TypeParameterLookup();
    lookup.pushEnclosingScopes(method.getEnclosingType());
    lookup.pushScope(method.getTypeParameters());
    int access = Opcodes.ACC_PUBLIC;
    Method reflectionMethod = reflectionMethods.get(method);
    String desc = Type.getMethodDescriptor(reflectionMethod);
    CollectMethodData methodData = new CollectMethodData(ClassType.TopLevel,
        access, method.getName(), desc, signature, null);
    Class<?>[] paramTypes = reflectionMethod.getParameterTypes();
    int n = paramTypes.length;
    Type[] argTypes = new Type[n];
    String[] argNames = new String[n];
    for (int i = 0; i < n; ++i) {
      argNames[i] = "arg" + i;
      argTypes[i] = Type.getType(paramTypes[i]);
    }
    ResolveMethodSignature methodResolver = new ResolveMethodSignature(
        resolver, failTreeLogger, method, lookup, true, methodData, argTypes,
        argNames, false, new MethodArgNamesLookup());
    new SignatureReader(signature).accept(methodResolver);
    methodResolver.finish();
  }
}
