/**
 * Copyright (C) 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.inject;

import static com.google.inject.Asserts.assertEqualsBothWays;
import static com.google.inject.Asserts.assertNotSerializable;
import static com.google.inject.util.Types.arrayOf;
import static com.google.inject.util.Types.listOf;
import static com.google.inject.util.Types.newParameterizedType;
import static com.google.inject.util.Types.newParameterizedTypeWithOwner;
import static com.google.inject.util.Types.setOf;

import com.google.common.collect.ImmutableList;
import com.google.inject.util.Types;

import junit.framework.TestCase;

import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.AbstractCollection;
import java.util.AbstractList;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * This test checks that TypeLiteral can perform type resolution on its members.
 *
 * @author jessewilson@google.com (Jesse Wilson)
 */
public class TypeLiteralTypeResolutionTest extends TestCase {
  Type arrayListOfString = newParameterizedType(ArrayList.class, String.class);
  Type hasGenericFieldsOfShort = newParameterizedTypeWithOwner(
      getClass(), HasGenericFields.class, Short.class);
  Type hasGenericConstructorOfShort = newParameterizedTypeWithOwner(
      getClass(), GenericConstructor.class, Short.class);
  Type throwerOfNpe = newParameterizedTypeWithOwner(
      getClass(), Thrower.class, NullPointerException.class);
  Type hasArrayOfShort = newParameterizedTypeWithOwner(getClass(), HasArray.class, Short.class);
  Type hasRelatedOfString = newParameterizedTypeWithOwner(
      getClass(), HasRelated.class, String.class, String.class);
  Type mapK = Map.class.getTypeParameters()[0];
  Type hashMapK = HashMap.class.getTypeParameters()[0];
  Type setEntryKV;
  Type entryStringInteger = setOf(newParameterizedTypeWithOwner(
      Map.class, Map.Entry.class, String.class, Integer.class));
  Field list;
  Field instance;
  Constructor<GenericConstructor> newHasGenericConstructor;
  Constructor<Thrower> newThrower;
  Constructor newString;
  Method stringIndexOf;
  Method comparableCompareTo;
  Method getArray;
  Method getSetOfArray;
  Method echo;
  Method throwS;

  @Override protected void setUp() throws Exception {
    super.setUp();

    list = HasGenericFields.class.getField("list");
    instance = HasGenericFields.class.getField("instance");
    newHasGenericConstructor = GenericConstructor.class.getConstructor(Object.class, Object.class);
    newThrower = Thrower.class.getConstructor();
    stringIndexOf = String.class.getMethod("indexOf", String.class);
    newString = String.class.getConstructor(String.class);
    comparableCompareTo = Comparable.class.getMethod("compareTo", Object.class);
    getArray = HasArray.class.getMethod("getArray");
    getSetOfArray = HasArray.class.getMethod("getSetOfArray");
    echo = HasRelated.class.getMethod("echo", Object.class);
    throwS = Thrower.class.getMethod("throwS");
    setEntryKV = HashMap.class.getMethod("entrySet").getGenericReturnType();
  }

  public void testDirectInheritance() throws NoSuchMethodException {
    TypeLiteral<?> resolver = TypeLiteral.get(arrayListOfString);
    assertEquals(listOf(String.class),
        resolver.getReturnType(List.class.getMethod("subList", int.class, int.class)).getType());
    assertEquals(ImmutableList.<TypeLiteral<?>>of(TypeLiteral.get(String.class)),
        resolver.getParameterTypes(Collection.class.getMethod("add", Object.class)));
  }
  
  public void testGenericSupertype() {
    TypeLiteral<?> resolver = TypeLiteral.get(arrayListOfString);
    assertEquals(newParameterizedType(Collection.class, String.class),
        resolver.getSupertype(Collection.class).getType());
    assertEquals(newParameterizedType(Iterable.class, String.class),
        resolver.getSupertype(Iterable.class).getType());
    assertEquals(newParameterizedType(AbstractList.class, String.class),
        resolver.getSupertype(AbstractList.class).getType());
    assertEquals(Object.class, resolver.getSupertype(Object.class).getType());
  }

  public void testRecursiveTypeVariable() {
    TypeLiteral<?> resolver = TypeLiteral.get(MyInteger.class);
    assertEquals(MyInteger.class, resolver.getParameterTypes(comparableCompareTo).get(0).getType());
  }

  interface MyComparable<E extends MyComparable<E>> extends Comparable<E> {}

  static class MyInteger implements MyComparable<MyInteger> {
    int value;
    public int compareTo(MyInteger o) {
      return value - o.value;
    }
  }
  
  public void testFields() {
    TypeLiteral<?> resolver = TypeLiteral.get(hasGenericFieldsOfShort);
    assertEquals(listOf(Short.class), resolver.getFieldType(list).getType());
    assertEquals(Short.class, resolver.getFieldType(instance).getType());
  }

  static class HasGenericFields<T> {
    public List<T> list;
    public T instance;
  }

  public void testGenericConstructor() throws NoSuchMethodException {
    TypeLiteral<?> resolver = TypeLiteral.get(hasGenericConstructorOfShort);
    assertEquals(Short.class,
        resolver.getParameterTypes(newHasGenericConstructor).get(0).getType());
  }

  static class GenericConstructor<S> {
    @SuppressWarnings("UnusedDeclaration")
    public <T> GenericConstructor(S s, T t) {}
  }

  public void testThrowsExceptions() {
    TypeLiteral<?> type = TypeLiteral.get(throwerOfNpe);
    assertEquals(NullPointerException.class, type.getExceptionTypes(newThrower).get(0).getType());
    assertEquals(NullPointerException.class, type.getExceptionTypes(throwS).get(0).getType());
  }

  static class Thrower<S extends Exception> {
    public Thrower() throws S {}
    public void throwS() throws S {}
  }

  public void testArrays() {
    TypeLiteral<?> resolver = TypeLiteral.get(hasArrayOfShort);
    assertEquals(arrayOf(Short.class), resolver.getReturnType(getArray).getType());
    assertEquals(setOf(arrayOf(Short.class)), resolver.getReturnType(getSetOfArray).getType());
  }

  static interface HasArray<T extends Number> {
    T[] getArray();
    Set<T[]> getSetOfArray();
  }

  public void testRelatedTypeVariables() {
    TypeLiteral<?> resolver = TypeLiteral.get(hasRelatedOfString);
    assertEquals(String.class, resolver.getParameterTypes(echo).get(0).getType());
    assertEquals(String.class, resolver.getReturnType(echo).getType());
  }

  interface HasRelated<T, R extends T> {
    T echo(R r);
  }

  /** Ensure the cache doesn't cache too much */
  public void testCachingAndReindexing() throws NoSuchMethodException {
    TypeLiteral<?> resolver = TypeLiteral.get(
        newParameterizedTypeWithOwner(getClass(), HasLists.class, String.class, Short.class));
    assertEquals(listOf(String.class),
        resolver.getReturnType(HasLists.class.getMethod("listS")).getType());
    assertEquals(listOf(Short.class),
        resolver.getReturnType(HasLists.class.getMethod("listT")).getType());
  }

  interface HasLists<S, T> {
    List<S> listS();
    List<T> listT();
    List<Map.Entry<S, T>> listEntries();
  }

  public void testUnsupportedQueries() throws NoSuchMethodException {
    TypeLiteral<?> resolver = TypeLiteral.get(arrayListOfString);

    try {
      resolver.getExceptionTypes(stringIndexOf);
      fail();
    } catch (IllegalArgumentException e) {
      assertEquals("public int java.lang.String.indexOf(java.lang.String) is not defined by a "
          + "supertype of java.util.ArrayList<java.lang.String>", e.getMessage());
    }
    try {
      resolver.getParameterTypes(stringIndexOf);
      fail();
    } catch (Exception e) {
      assertEquals("public int java.lang.String.indexOf(java.lang.String) is not defined by a "
          + "supertype of java.util.ArrayList<java.lang.String>", e.getMessage());
    }
    try {
      resolver.getReturnType(stringIndexOf);
      fail();
    } catch (Exception e) {
      assertEquals("public int java.lang.String.indexOf(java.lang.String) is not defined by a "
          + "supertype of java.util.ArrayList<java.lang.String>", e.getMessage());
    }
    try {
      resolver.getSupertype(String.class);
      fail();
    } catch (Exception e) {
      assertEquals("class java.lang.String is not a supertype of "
          + "java.util.ArrayList<java.lang.String>", e.getMessage());
    }
    try {
      resolver.getExceptionTypes(newString);
      fail();
    } catch (Exception e) {
      assertEquals("public java.lang.String(java.lang.String) does not construct "
          + "a supertype of java.util.ArrayList<java.lang.String>", e.getMessage());
    }
    try {
      resolver.getParameterTypes(newString);
      fail();
    } catch (Exception e) {
      assertEquals("public java.lang.String(java.lang.String) does not construct "
          + "a supertype of java.util.ArrayList<java.lang.String>", e.getMessage());
    }
  }

  public void testResolve() {
    TypeLiteral<?> typeResolver = TypeLiteral.get(StringIntegerMap.class);
    assertEquals(String.class, typeResolver.resolveType(mapK));

    typeResolver = new TypeLiteral<Map<String, Integer>>() {};
    assertEquals(String.class, typeResolver.resolveType(mapK));
    assertEquals(Types.mapOf(String.class, Integer.class),
        typeResolver.getSupertype(Map.class).getType());

    typeResolver = new TypeLiteral<BetterMap<String, Integer>>() {};
    assertEquals(String.class, typeResolver.resolveType(mapK));

    typeResolver = new TypeLiteral<BestMap<String, Integer>>() {};
    assertEquals(String.class, typeResolver.resolveType(mapK));

    typeResolver = TypeLiteral.get(StringIntegerHashMap.class);
    assertEquals(String.class, typeResolver.resolveType(mapK));
    assertEquals(String.class, typeResolver.resolveType(hashMapK));
    assertEquals(entryStringInteger, typeResolver.resolveType(setEntryKV));
    assertEquals(Object.class, typeResolver.getSupertype(Object.class).getType());
  }

  public void testOnObject() {
    TypeLiteral<?> typeResolver = TypeLiteral.get(Object.class);
    assertEquals(Object.class, typeResolver.getSupertype(Object.class).getType());
    assertEquals(Object.class, typeResolver.getRawType());

    // interfaces also resolve Object
    typeResolver = TypeLiteral.get(Types.setOf(Integer.class));
    assertEquals(Object.class, typeResolver.getSupertype(Object.class).getType());
  }

  interface StringIntegerMap extends Map<String, Integer> {}
  interface BetterMap<K1, V1> extends Map<K1, V1> {}
  interface BestMap<K2, V2> extends BetterMap<K2, V2> {}
  static class StringIntegerHashMap extends HashMap<String, Integer> {}

  public void testGetSupertype() {
    TypeLiteral<AbstractList<String>> listOfString = new TypeLiteral<AbstractList<String>>() {};
    assertEquals(Types.newParameterizedType(AbstractCollection.class, String.class),
        listOfString.getSupertype(AbstractCollection.class).getType());

    TypeLiteral arrayListOfE = TypeLiteral.get(newParameterizedType(
        ArrayList.class, ArrayList.class.getTypeParameters()));
    assertEquals(
        newParameterizedType(AbstractCollection.class, ArrayList.class.getTypeParameters()),
        arrayListOfE.getSupertype(AbstractCollection.class).getType());
  }

  public void testGetSupertypeForArraysAsList() {
    Class<? extends List> arraysAsListClass = Arrays.asList().getClass();
    Type anotherE = arraysAsListClass.getTypeParameters()[0];
    TypeLiteral type = TypeLiteral.get(newParameterizedType(AbstractList.class, anotherE));
    assertEquals(newParameterizedType(AbstractCollection.class, anotherE),
        type.getSupertype(AbstractCollection.class).getType());
  }

  public void testWildcards() throws NoSuchFieldException {
    TypeLiteral<Parameterized<String>> ofString = new TypeLiteral<Parameterized<String>>() {};

    assertEquals(new TypeLiteral<List<String>>() {}.getType(),
        ofString.getFieldType(Parameterized.class.getField("t")).getType());
    assertEquals(new TypeLiteral<List<? extends String>>() {}.getType(),
        ofString.getFieldType(Parameterized.class.getField("extendsT")).getType());
    assertEquals(new TypeLiteral<List<? super String>>() {}.getType(),
        ofString.getFieldType(Parameterized.class.getField("superT")).getType());
  }

  static class Parameterized<T> {
    public List<T> t;
    public List<? extends T> extendsT;
    public List<? super T> superT;
  }

  // TODO(jessewilson): tests for tricky bounded types like <T extends Collection, Serializable>

  public void testEqualsAndHashCode() throws IOException {
    TypeLiteral<?> a1 = TypeLiteral.get(arrayListOfString);
    TypeLiteral<?> a2 = TypeLiteral.get(arrayListOfString);
    TypeLiteral<?> b = TypeLiteral.get(listOf(String.class));
    assertEqualsBothWays(a1, a2);
    assertNotSerializable(a1);
    assertFalse(a1.equals(b));
  }
}
