/*
 * 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.core.ext.typeinfo;

import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.typeinfo.test.EnumInterface;
import com.google.gwt.core.ext.typeinfo.test.EnumOfInterface;
import com.google.gwt.core.ext.typeinfo.test.MyEnum;
import com.google.gwt.core.ext.typeinfo.test.TestAnnotation;
import com.google.gwt.dev.util.log.PrintWriterTreeLogger;

import junit.framework.TestCase;

/**
 * Tests for {@link JEnumType}.
 */
public class JEnumTypeTest extends TestCase {

  private final boolean logToConsole = false;

  private final ModuleContext moduleContext = new ModuleContext(logToConsole
      ? new PrintWriterTreeLogger() : TreeLogger.NULL,
      "com.google.gwt.core.ext.typeinfo.TypeOracleTest");

  public JEnumTypeTest() throws UnableToCompleteException {
  }

  private final TypeOracle typeOracle = moduleContext.getOracle();

  /**
   * Test method for
   * {@link com.google.gwt.core.ext.typeinfo.JEnumType#getEnumConstants()}.
   * 
   * @throws NotFoundException
   */
  public void testGetEnumConstants() throws NotFoundException {
    JClassType type = typeOracle.getType(MyEnum.class.getName());
    JEnumType enumType = type.isEnum();
    assertNotNull(enumType);

    JEnumConstant[] enumConstants = enumType.getEnumConstants();
    assertEquals(3, enumConstants.length);

    for (int i = 0; i < enumConstants.length; ++i) {
      JEnumConstant enumConstant = enumConstants[i];
      // Check the ordinal
      assertEquals(i, enumConstant.getOrdinal());

      // Check that the name matches what reflection expects at the current
      // ordinal.
      assertEquals(MyEnum.class.getEnumConstants()[i].name(),
          enumConstant.getName());
    }
  }

  /**
   * Test method for
   * {@link com.google.gwt.core.ext.typeinfo.JClassType#getFields()}.
   * 
   * @throws NotFoundException
   */
  public void testGetFields() throws NotFoundException {
    JClassType type = typeOracle.getType(MyEnum.class.getName());
    JEnumType enumType = validateTypeIsEnum(type);

    assertEquals(5, enumType.getFields().length);
  }

  /**
   * Test method for
   * {@link com.google.gwt.core.ext.typeinfo.JClassType#getField(String)}.
   * 
   * @throws NotFoundException
   */
  public void testGetFieldString() throws NotFoundException {
    JClassType type = typeOracle.getType(MyEnum.class.getName());

    validateTypeIsEnum(type);

    type.getField("VAL0");
    type.getField("VAL1");
    type.getField("VAL2");
    type.getField("instanceField");
    type.getField("e");
  }

  /**
   * Test method for {@link JEnumType#getConstructors()}
   * 
   * @throws NotFoundException
   * @throws NotFoundException
   */
  public void testGetConstructors() throws NotFoundException {
    JClassType type = typeOracle.getType(MyEnum.class.getName());
    JEnumType enumType = validateTypeIsEnum(type);

    // Enum constructors are not reflected.
    assertEquals(0, enumType.getConstructors().length);
  }

  /**
   * Test method for {@link JEnumType#getMethods()}
   * 
   * @throws NotFoundException
   */
  public void testGetMethods() throws NotFoundException {
    JClassType type = typeOracle.getType(MyEnum.class.getName());
    JEnumType enumType = validateTypeIsEnum(type);

    assertEquals(3, enumType.getMethods().length);
  }

  /**
   * Test an enum that implements an interface.
   * 
   * @throws NotFoundException 
   */
  public void testInterface() throws NotFoundException {
    JClassType type = typeOracle.getType(EnumOfInterface.class.getName());
    JEnumType enumType = validateTypeIsEnum(type);
    JClassType[] intf = enumType.getImplementedInterfaces();
    assertEquals(1, intf.length);
    assertEquals(EnumInterface.class.getName(),
        intf[0].getQualifiedSourceName());
    JMethod getExtra = intf[0].getMethod("getExtra", new JType[0]);
    TestAnnotation annotation = getExtra.getAnnotation(TestAnnotation.class);
    assertNotNull(annotation);
    assertEquals("EnumInterface getExtra", annotation.value());
    JEnumConstant[] constants = enumType.getEnumConstants();
    assertEquals(2, constants.length);
    assertEquals("A", constants[0].getName());
    annotation = constants[0].getAnnotation(TestAnnotation.class);
    assertNotNull(annotation);
    assertEquals("A", annotation.value());
    JClassType aClass = constants[0].getType().isClass();
    {
      JMethod[] methods = aClass.getInheritableMethods();
      assertEquals(11, methods.length);
      boolean found = false;
      for (JMethod method : methods) {
        if ("name".equals(method.getName())) {
          found = true;
          // TODO(jat); any other verification here?
        }
      }
      assertTrue(found);
    }
    {
      JMethod[] methods = aClass.getOverridableMethods();
      assertEquals(4, methods.length);
      // TODO(jat): verify getExtra is from A's anonymous subclass of
      // EnumInterface when/if that is implemented.
      boolean found = false;
      for (JMethod method : methods) {
        if ("getExtra".equals(method.getName())) {
          found = true;
          // TODO(jat); any other verification here?
        }
      }
      assertTrue(found);
    }
  }

  /**
   * Test method for {@link com.google.gwt.core.ext.typeinfo.JEnumType#isEnum()}.
   * 
   * @throws NotFoundException
   */
  public void testIsEnum() throws NotFoundException {
    JClassType type = typeOracle.getType(MyEnum.class.getName());
    validateTypeIsEnum(type);
  }

  private static JEnumType validateTypeIsEnum(JClassType type)
      throws NotFoundException {
    JEnumType maybeEnum = type.isEnum();
    assertNotNull(maybeEnum);

    JClassType enumType = type.getOracle().getType(Enum.class.getName());

    assertTrue(enumType.isAssignableFrom(maybeEnum));

    return maybeEnum;
  }
}
