/*
 * Copyright 2008 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.typemodel;

import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.typeinfo.HasAnnotations;
import com.google.gwt.core.ext.typeinfo.JPrimitiveType;
import com.google.gwt.core.ext.typeinfo.JType;
import com.google.gwt.core.ext.typeinfo.NotFoundException;
import com.google.gwt.dev.javac.typemodel.test.AnnotatedClass;
import com.google.gwt.dev.javac.typemodel.test.ClassAnnotatedWithBinaryOnlyAnnotation;
import com.google.gwt.dev.javac.typemodel.test.ClassLiteralReferenceAnnotation;
import com.google.gwt.dev.javac.typemodel.test.PrimitiveValuesAnnotation;
import com.google.gwt.dev.javac.typemodel.test.PrimitivesAnnotatedClass;
import com.google.gwt.dev.javac.typemodel.test.SourceRetentionAnnotation;
import com.google.gwt.dev.javac.typemodel.test.TestAnnotation;
import com.google.gwt.dev.util.log.PrintWriterTreeLogger;

import junit.framework.TestCase;

import java.io.File;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

/**
 * Test cases for the {@link TypeOracle}'s {@link Annotation} support.
 * 
 * Array annotations Enum annotations String from field annotations
 */
public class TypeOracleAnnotationSupportTest extends TestCase {

  private static void validateAnnotation(HasAnnotations annotatedElement,
      String testAnnotationValue, String nestedAnnotationValue,
      TestAnnotation realAnnotation) {
    assertNotNull(annotatedElement);

    assertNull(annotatedElement.getAnnotation(SourceRetentionAnnotation.class));

    TestAnnotation testAnnotation = annotatedElement.getAnnotation(TestAnnotation.class);
    assertNotNull(testAnnotation);

    // Check our proxy objects against the real thing.
    assertEquals(realAnnotation, testAnnotation);
    assertEquals(realAnnotation.hashCode(), testAnnotation.hashCode());

    // tobyr doesn't like this.
    // assertEquals(realAnnotation.toString(), testAnnotation.toString());

    // checks default value
    assertEquals(testAnnotationValue, testAnnotation.value());
    assertEquals(nestedAnnotationValue,
        testAnnotation.nestedAnnotation().value());

    // Tests default values using conditional statements.
    assertEquals(realAnnotation.longValue(), testAnnotation.longValue());

    // Tests default value of array type.
    assertEquals(realAnnotation.intArrayValue().length,
        testAnnotation.intArrayValue().length);

    // Tests default value which is a field reference.
    assertEquals(realAnnotation.stringValue(), testAnnotation.stringValue());

    // Tests default value that is a class literal.
    assertEquals(realAnnotation.classLiteral(), testAnnotation.classLiteral());

    // Tests implicit array initializers
    Class<?>[] expectedArrayValue = realAnnotation.arrayWithImplicitArrayInitializer();
    Class<?>[] actualArrayValue = testAnnotation.arrayWithImplicitArrayInitializer();
    assertTrue(expectedArrayValue.length > 0);
    assertEquals(expectedArrayValue.length, actualArrayValue.length);
    assertEquals(expectedArrayValue[0], actualArrayValue[0]);

    // Tests that empty array initializers are also handled correctly.
    assertEquals(realAnnotation.emptyArray().length,
        testAnnotation.emptyArray().length);
  }

  private final boolean logToConsole = false;
  private final ModuleContext moduleContext = new ModuleContext(logToConsole
      ? new PrintWriterTreeLogger() : TreeLogger.NULL,
      "com.google.gwt.dev.javac.typemodel.TypeOracleTest");

  private final TypeOracle typeOracle = moduleContext.getOracle();

  public TypeOracleAnnotationSupportTest() throws UnableToCompleteException {
  }

  /**
   * Test that a class can be annotated.
   */
  public void testAnnotatedClass() throws NotFoundException {
    JClassType annotatedClass = typeOracle.getType(AnnotatedClass.class.getName());

    TestAnnotation realAnnotation = AnnotatedClass.class.getAnnotation(TestAnnotation.class);
    validateAnnotation(annotatedClass, "Class", "Foo", realAnnotation);

    ClassLiteralReferenceAnnotation classReferenceAnnotation = annotatedClass.getAnnotation(ClassLiteralReferenceAnnotation.class);
    assertEquals(ClassLiteralReferenceAnnotation.Foo.class,
        classReferenceAnnotation.value());

    assertEquals(2, annotatedClass.getAnnotations().length);
  }

  /**
   * Test that a constructor can be annotated.
   */
  public void testAnnotatedConstructor() throws NotFoundException,
      SecurityException, NoSuchMethodException {
    JClassType annotatedClass = typeOracle.getType(AnnotatedClass.class.getName());
    JConstructor ctor = annotatedClass.getConstructor(TypeOracle.NO_JTYPES);

    Constructor<AnnotatedClass> constructor = AnnotatedClass.class.getConstructor();
    TestAnnotation realAnnotation = constructor.getAnnotation(TestAnnotation.class);

    validateAnnotation(ctor, "Constructor", "Not assigned", realAnnotation);
  }

  /**
   * Test that a field can be annotated.
   */
  public void testAnnotatedField() throws NotFoundException, SecurityException,
      NoSuchFieldException {
    JClassType annotatedClass = typeOracle.getType(AnnotatedClass.class.getName());
    JField annotatedField = annotatedClass.getField("annotatedField");

    Field field = AnnotatedClass.class.getDeclaredField("annotatedField");
    TestAnnotation realAnnotation = field.getAnnotation(TestAnnotation.class);

    validateAnnotation(annotatedField, "Field", "Not assigned", realAnnotation);
  }

  /**
   * Tests that methods can be annotated.
   */
  public void testAnnotatedMethod() throws NotFoundException,
      SecurityException, NoSuchMethodException {
    JClassType annotatedClass = typeOracle.getType(AnnotatedClass.class.getName());
    JMethod annotatedMethod = annotatedClass.getMethod("annotatedMethod",
        TypeOracle.NO_JTYPES);

    Method method = AnnotatedClass.class.getDeclaredMethod("annotatedMethod");
    TestAnnotation realAnnotation = method.getAnnotation(TestAnnotation.class);

    validateAnnotation(annotatedMethod, "Method", "Not assigned",
        realAnnotation);
  }

  /**
   * Tests that packages can be annotated. This necessitates the existence of a
   * package-info.java file in the package that you wish to annotate.
   */
  public void testAnnotatedPackage() throws NotFoundException,
      ClassNotFoundException {
    JPackage annotatedPackage = typeOracle.getPackage("com.google.gwt.dev.javac.typemodel.test");
    assertNotNull(annotatedPackage);

    TestAnnotation realAnnotation = Class.forName(
        "com.google.gwt.dev.javac.typemodel.test.package-info", false,
        TypeOracleAnnotationSupportTest.class.getClassLoader()).getAnnotation(
        TestAnnotation.class);

    validateAnnotation(annotatedPackage, "Package", "Not assigned",
        realAnnotation);
  }

  /**
   * Tests that parameters can be annotated.
   */
  public void testAnnotatedParameter() throws NotFoundException,
      SecurityException, NoSuchMethodException {
    JClassType annotatedClass = typeOracle.getType(AnnotatedClass.class.getName());
    JMethod jmethod = annotatedClass.getMethod("methodWithAnnotatedParameter",
        new JType[]{JPrimitiveType.INT});
    JParameter parameter = jmethod.getParameters()[0];

    Method method = AnnotatedClass.class.getDeclaredMethod(
        "methodWithAnnotatedParameter", int.class);
    Annotation[][] paramAnnotations = method.getParameterAnnotations();
    TestAnnotation realAnnotation = (TestAnnotation) paramAnnotations[0][0];

    validateAnnotation(parameter, "Parameter", "Not assigned", realAnnotation);
  }

  public void testAnnotatedWithArrayOfClasses() throws NotFoundException,
      SecurityException, NoSuchMethodException {
    JClassType annotatedClass = typeOracle.getType(AnnotatedClass.class.getName());
    JMethod annotatedMethod = annotatedClass.getMethod(
        "annotatedWithArrayOfClasses", TypeOracle.NO_JTYPES);

    Method method = AnnotatedClass.class.getDeclaredMethod("annotatedWithArrayOfClasses");
    TestAnnotation realAnnotation = method.getAnnotation(TestAnnotation.class);

    validateAnnotation(annotatedMethod, "Method", "Not assigned",
        realAnnotation);
  }

  /**
   * Tests translatable classes that are annotated with annotations for which we
   * have no source.
   */
  public void testBinaryOnlyAnnotation() throws NotFoundException {
    // It is an error if we fail to get the type.
    JClassType classType = typeOracle.getType(ClassAnnotatedWithBinaryOnlyAnnotation.class.getCanonicalName());

    BinaryOnlyAnnotation annotation = classType.getAnnotation(BinaryOnlyAnnotation.class);
    assertNotNull(annotation);
    assertEquals(File.class, annotation.jreClassLiteralReference());
  }

  /**
   * Ensures that we properly handle primitive value attributes on annotations.
   * (Special-cased, because of how JDT handles char/numeric literals)
   */
  public void testPrimitiveValuesAnnotations() throws NotFoundException {
    JClassType primitivesAnnotatedClass = typeOracle.getType(PrimitivesAnnotatedClass.class.getName());
    PrimitiveValuesAnnotation annotation = primitivesAnnotatedClass.getAnnotation(PrimitiveValuesAnnotation.class);

    boolean bool = annotation.bool();
    assertTrue(bool);

    byte b = annotation.b();
    assertTrue(b > 0);

    char c = annotation.c();
    assertTrue(c > 0);

    double d = annotation.d();
    assertTrue(d > 0);

    float f = annotation.f();
    assertTrue(f > 0);

    int i = annotation.i();
    assertTrue(i > 0);

    long l = annotation.l();
    assertTrue(l > 0);

    short s = annotation.s();
    assertTrue(s > 0);

    int[] ia = annotation.ia();
    assertEquals(3, ia.length);
    for (int it = 0; it < 3; ++it) {
      assertEquals(it, ia[it]);
    }
  }
}
