/*
 * 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.dev.javac.typemodel.test.PrimitiveValuesAnnotation;
import com.google.gwt.dev.javac.typemodel.test.TestAnnotation;
import com.google.gwt.dev.asm.AnnotationVisitor;
import com.google.gwt.dev.asm.ClassReader;
import com.google.gwt.dev.asm.Opcodes;
import com.google.gwt.dev.asm.Type;
import com.google.gwt.dev.asm.commons.EmptyVisitor;
import com.google.gwt.dev.javac.asm.CollectAnnotationData.AnnotationData;
import com.google.gwt.dev.javac.asm.CollectClassData.ClassType;

import java.util.List;

/**
 * Tests for {@link CollectClassData}.
 */
public class CollectClassDataTest extends AsmTestCase {

  public static class One extends EmptyVisitor {

    @Override
    public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
      new EmptyVisitor() {
        @Override
        public void visit(int version, int access, String name,
            String signature, String superName, String[] interfaces) {
        }
      };
      return new CollectAnnotationData(desc, visible);
    }
  }

  @PrimitiveValuesAnnotation(b = 42, i = 42)
  protected static class Two {

    public class TwoInner {
    }

    private final String field;

    @TestAnnotation("field")
    private final String annotatedField;

    public Two(int a) {
      this(a, null);
    }

    @TestAnnotation("foo")
    public String foo(int a) throws IllegalStateException {
      return annotatedField;
    }

    public Two(int a, String b) {
      new TwoInner();
      field = b;
      annotatedField = field;
    }
  }

  /**
   * Test local classes.
   */
  public static class Three {

    public int foo;

    /**
     * Static method that has a local class in it.
     */
    public static void methodWithLocalStatic() {
      class Foo {
      }

      Foo x = new Foo();
    }

    /**
     * Method that has a local class in it.
     */
    public void methodWithLocal() {
      class Foo {
        Foo() {
          foo = 1;
        }
      }

      Foo x = new Foo();
    }
  }

  public void testAnonymous() {
    CollectClassData cd = collect(One.class.getName() + "$1");
    // Don't access on anonymous classes, it varies among compilers
    // assertEquals(0, cd.getAccess() & ~Opcodes.ACC_SUPER);
    assertEquals(ClassType.Anonymous, cd.getClassType());
    assertEquals(0, cd.getFields().size());
    List<CollectMethodData> methods = cd.getMethods();
    assertEquals(2, methods.size());
  }

  public void testOne() {
    CollectClassData cd = collect(One.class);
    // Don't check for super bit, as it will depend on the JDK used to compile.
    assertEquals(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, cd.getAccess()
        & ~Opcodes.ACC_SUPER);
    assertEquals(ClassType.Nested, cd.getClassType());
    assertEquals(0, cd.getFields().size());
    assertEquals(0, cd.getInterfaces().length);
    assertEquals(0, cd.getAnnotations().size());
    assertEquals("com/google/gwt/dev/asm/commons/EmptyVisitor",
        cd.getSuperName());

    List<CollectMethodData> methods = cd.getMethods();
    assertEquals(2, methods.size());
    // TODO(jat): Is it safe to assume the implicit constructor is always first?
    CollectMethodData method = methods.get(0);
    Type[] argTypes = method.getArgTypes();
    String[] argNames = method.getArgNames();
    assertEquals("<init>", method.getName());
    assertEquals(0, argTypes.length);
    assertEquals(0, argNames.length);
    assertEquals(0, method.getArgAnnotations().length);
    assertEquals(0, method.getAnnotations().size());
    assertEquals(0, method.getExceptions().length);

    method = methods.get(1);
    argTypes = method.getArgTypes();
    argNames = method.getArgNames();
    assertEquals("visitAnnotation", method.getName());
    assertEquals(2, argTypes.length);
    assertEquals("java.lang.String", argTypes[0].getClassName());
    assertEquals("boolean", argTypes[1].getClassName());
    assertEquals(2, argNames.length);
    assertEquals("desc", argNames[0]);
    assertEquals("visible", argNames[1]);
    assertEquals(2, method.getArgAnnotations().length);
    assertEquals(0, method.getArgAnnotations()[0].size());
    assertEquals(0, method.getArgAnnotations()[1].size());
    // Note that @Override is a source-only annotation
    assertEquals(0, method.getAnnotations().size());
    assertEquals(0, method.getExceptions().length);
  }

  public void testTopLevel() {
    CollectClassData cd = collect(CollectClassDataTest.class);
    // Don't check for super bit, as it will depend on the JDK used to compile.
    assertEquals(Opcodes.ACC_PUBLIC, cd.getAccess() & ~Opcodes.ACC_SUPER);
    assertEquals(ClassType.TopLevel, cd.getClassType());
  }

  public void testTwo() {
    CollectClassData cd = collect(Two.class);
    // Don't check for super bit, as it will depend on the JDK used to compile.
    assertEquals(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, cd.getAccess()
        & ~Opcodes.ACC_SUPER);
    assertEquals(ClassType.Nested, cd.getClassType());
    List<CollectFieldData> fields = cd.getFields();
    assertEquals(2, fields.size());
    CollectFieldData field = fields.get(0);
    assertEquals("field", field.getName());
    assertEquals("Ljava/lang/String;", field.getDesc());
    List<CollectAnnotationData> annotations = field.getAnnotations();
    assertEquals(0, annotations.size());
    field = fields.get(1);
    assertEquals("annotatedField", field.getName());
    assertEquals("Ljava/lang/String;", field.getDesc());
    annotations = field.getAnnotations();
    assertEquals(1, annotations.size());
    AnnotationData annotation = annotations.get(0).getAnnotation();
    assertEquals("Lcom/google/gwt/dev/javac/typemodel/test/TestAnnotation;",
        annotation.getDesc());
    assertEquals("field", annotation.getValues().get("value"));
    assertEquals(0, cd.getInterfaces().length);
    annotations = cd.getAnnotations();
    assertEquals(1, annotations.size());
    annotation = annotations.get(0).getAnnotation();
    assertEquals(
        "Lcom/google/gwt/dev/javac/typemodel/test/PrimitiveValuesAnnotation;",
        annotation.getDesc());
    assertEquals(Byte.valueOf((byte) 42), annotation.getValues().get("b"));
    assertEquals(42, annotation.getValues().get("i"));
    assertEquals("java/lang/Object", cd.getSuperName());

    List<CollectMethodData> methods = cd.getMethods();
    assertEquals(3, methods.size());
    // TODO(jat): Is it safe to assume the order?
    CollectMethodData method = methods.get(0);
    Type[] argTypes = method.getArgTypes();
    String[] argNames = method.getArgNames();
    assertEquals("<init>", method.getName());
    assertEquals(1, argTypes.length);
    assertEquals(1, argNames.length);
    assertEquals(1, method.getArgAnnotations().length);
    assertEquals(0, method.getAnnotations().size());
    assertEquals(0, method.getExceptions().length);

    method = methods.get(1);
    argTypes = method.getArgTypes();
    argNames = method.getArgNames();
    assertEquals("foo", method.getName());
    assertEquals(1, argTypes.length);
    assertEquals("int", argTypes[0].getClassName());
    assertEquals(1, argNames.length);
    assertEquals("a", argNames[0]);
    assertEquals(1, method.getArgAnnotations().length);
    assertEquals(0, method.getArgAnnotations()[0].size());
    assertEquals(1, method.getAnnotations().size());
    assertEquals(1, method.getExceptions().length);

    method = methods.get(2);
    argTypes = method.getArgTypes();
    argNames = method.getArgNames();
    assertEquals("<init>", method.getName());
    assertEquals(2, argTypes.length);
    assertEquals("int", argTypes[0].getClassName());
    assertEquals("java.lang.String", argTypes[1].getClassName());
    assertEquals(2, argNames.length);
    assertEquals("a", argNames[0]);
    assertEquals("b", argNames[1]);
    assertEquals(2, method.getArgAnnotations().length);
    assertEquals(0, method.getArgAnnotations()[0].size());
    assertEquals(0, method.getArgAnnotations()[1].size());
    assertEquals(0, method.getAnnotations().size());
    assertEquals(0, method.getExceptions().length);
  }

  public void testTwoInner() {
    CollectClassData cd = collect(Two.TwoInner.class);
    // Don't check for super bit, as it will depend on the JDK used to compile.
    assertEquals(Opcodes.ACC_PUBLIC, cd.getAccess() & ~Opcodes.ACC_SUPER);
    assertEquals(ClassType.Inner, cd.getClassType());
  }

  public void testLocal() {
    CollectClassData cd = collect(Three.class.getName() + "$2Foo");
    // Don't check for super bit, as it will depend on the JDK used to compile.
    assertEquals(0, cd.getAccess() & ~Opcodes.ACC_SUPER);
    assertEquals(ClassType.Local, cd.getClassType());
    assertEquals("methodWithLocal", cd.getOuterMethodName());
  }

  public void testLocalStatic() {
    CollectClassData cd = collect(Three.class.getName() + "$1Foo");
    // Don't check for super bit, as it will depend on the JDK used to compile.
    assertEquals(0, cd.getAccess() & ~Opcodes.ACC_SUPER);
    assertEquals(ClassType.Local, cd.getClassType());
    assertEquals("methodWithLocalStatic", cd.getOuterMethodName());
  }

  private CollectClassData collect(Class<?> clazz) {
    return collect(clazz.getName());
  }

  private CollectClassData collect(String className) {
    byte[] bytes = getClassBytes(className);
    assertNotNull("Couldn't load bytes for " + className, bytes);
    CollectClassData cv = new CollectClassData();
    ClassReader reader = new ClassReader(bytes);
    reader.accept(cv, 0);
    return cv;
  }
}
