/*
 * Copyright (C) 2009 The Guava Authors
 *
 * 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.common.reflect;

import static com.google.common.truth.Truth.assertThat;

import com.google.common.base.Predicate;
import com.google.common.base.Supplier;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.lang.reflect.WildcardType;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import junit.framework.TestCase;

/**
 * Unit test for {@link TypeToken} and {@link TypeResolver}.
 *
 * @author Ben Yu
 */
@AndroidIncompatible // lots of failures, possibly some related to bad equals() implementations?
public class TypeTokenResolutionTest extends TestCase {

  private static class Foo<A, B> {

    Class<? super A> getClassA() {
      return new TypeToken<A>(getClass()) {}.getRawType();
    }

    Class<? super B> getClassB() {
      return new TypeToken<B>(getClass()) {}.getRawType();
    }

    Class<? super A[]> getArrayClassA() {
      return new TypeToken<A[]>(getClass()) {}.getRawType();
    }

    Type getArrayTypeA() {
      return new TypeToken<A[]>(getClass()) {}.getType();
    }

    Class<? super B[]> getArrayClassB() {
      return new TypeToken<B[]>(getClass()) {}.getRawType();
    }
  }

  public void testSimpleTypeToken() {
    Foo<String, Integer> foo = new Foo<String, Integer>() {};
    assertEquals(String.class, foo.getClassA());
    assertEquals(Integer.class, foo.getClassB());
    assertEquals(String[].class, foo.getArrayClassA());
    assertEquals(Integer[].class, foo.getArrayClassB());
  }

  public void testCompositeTypeToken() {
    Foo<String[], List<int[]>> foo = new Foo<String[], List<int[]>>() {};
    assertEquals(String[].class, foo.getClassA());
    assertEquals(List.class, foo.getClassB());
    assertEquals(String[][].class, foo.getArrayClassA());
    assertEquals(List[].class, foo.getArrayClassB());
  }

  private static class StringFoo<T> extends Foo<String, T> {}

  public void testPartialSpecialization() {
    StringFoo<Integer> foo = new StringFoo<Integer>() {};
    assertEquals(String.class, foo.getClassA());
    assertEquals(Integer.class, foo.getClassB());
    assertEquals(String[].class, foo.getArrayClassA());
    assertEquals(Integer[].class, foo.getArrayClassB());
    assertEquals(new TypeToken<String[]>() {}.getType(), foo.getArrayTypeA());
  }

  public void testTypeArgNotFound() {
    StringFoo<Integer> foo = new StringFoo<>();
    assertEquals(String.class, foo.getClassA());
    assertEquals(String[].class, foo.getArrayClassA());
    assertEquals(Object.class, foo.getClassB());
    assertEquals(Object[].class, foo.getArrayClassB());
  }

  private abstract static class Bar<T> {}

  private abstract static class Parameterized<O, T, P> {
    ParameterizedType parameterizedType() {
      return new ParameterizedType() {
        @Override
        public Type[] getActualTypeArguments() {
          return new Type[] {new TypeCapture<P>() {}.capture()};
        }

        @Override
        public Type getOwnerType() {
          return new TypeCapture<O>() {}.capture();
        }

        @Override
        public Type getRawType() {
          return new TypeCapture<T>() {}.capture();
        }
      };
    }
  }

  public void testResolveType_parameterizedType() {
    @SuppressWarnings("rawtypes") // trying to test raw type
    Parameterized<?, ?, ?> parameterized =
        new Parameterized<TypeTokenResolutionTest, Bar, String>() {};
    TypeResolver typeResolver = TypeResolver.covariantly(parameterized.getClass());
    ParameterizedType resolved =
        (ParameterizedType) typeResolver.resolveType(parameterized.parameterizedType());
    assertEquals(TypeTokenResolutionTest.class, resolved.getOwnerType());
    assertEquals(Bar.class, resolved.getRawType());
    assertThat(resolved.getActualTypeArguments()).asList().contains(String.class);
  }

  private interface StringListPredicate extends Predicate<List<String>> {}

  private interface IntegerSupplier extends Supplier<Integer> {}

  // Intentionally duplicate the Predicate interface to test that it won't cause
  // exceptions
  private interface IntegerStringFunction
      extends IntegerSupplier, Predicate<List<String>>, StringListPredicate {}

  public void testGenericInterface() {
    // test the 1st generic interface on the class
    Type fType = Supplier.class.getTypeParameters()[0];
    assertEquals(
        Integer.class, TypeToken.of(IntegerStringFunction.class).resolveType(fType).getRawType());

    // test the 2nd generic interface on the class
    Type predicateParameterType = Predicate.class.getTypeParameters()[0];
    assertEquals(
        new TypeToken<List<String>>() {}.getType(),
        TypeToken.of(IntegerStringFunction.class).resolveType(predicateParameterType).getType());
  }

  private abstract static class StringIntegerFoo extends Foo<String, Integer> {}

  public void testConstructor_typeArgsResolvedFromAncestorClass() {
    assertEquals(String.class, new StringIntegerFoo() {}.getClassA());
    assertEquals(Integer.class, new StringIntegerFoo() {}.getClassB());
  }

  private static class Owner<T> {
    private abstract static class Nested<X> {
      Class<? super X> getTypeArgument() {
        return new TypeToken<X>(getClass()) {}.getRawType();
      }
    }

    private abstract class Inner<Y> extends Nested<Y> {
      Class<? super T> getOwnerType() {
        return new TypeToken<T>(getClass()) {}.getRawType();
      }
    }
  }

  public void testResolveNestedClass() {
    assertEquals(String.class, new Owner.Nested<String>() {}.getTypeArgument());
  }

  public void testResolveInnerClass() {
    assertEquals(String.class, new Owner<Integer>().new Inner<String>() {}.getTypeArgument());
  }

  public void testResolveOwnerClass() {
    assertEquals(Integer.class, new Owner<Integer>().new Inner<String>() {}.getOwnerType());
  }

  private static class Mapping<F, T> {

    final Type f = new TypeToken<F>(getClass()) {}.getType();
    final Type t = new TypeToken<T>(getClass()) {}.getType();

    Type getFromType() {
      return new TypeToken<F>(getClass()) {}.getType();
    }

    Type getToType() {
      return new TypeToken<T>(getClass()) {}.getType();
    }

    Mapping<T, F> flip() {
      return new Mapping<T, F>() {};
    }

    Mapping<F, T> selfMapping() {
      return new Mapping<F, T>() {};
    }
  }

  public void testCyclicMapping() {
    Mapping<Integer, String> mapping = new Mapping<>();
    assertEquals(mapping.f, mapping.getFromType());
    assertEquals(mapping.t, mapping.getToType());
    assertEquals(mapping.f, mapping.flip().getFromType());
    assertEquals(mapping.t, mapping.flip().getToType());
    assertEquals(mapping.f, mapping.selfMapping().getFromType());
    assertEquals(mapping.t, mapping.selfMapping().getToType());
  }

  private static class ParameterizedOuter<T> {

    @SuppressWarnings("unused") // used by reflection
    public Inner field;

    class Inner {}
  }

  public void testInnerClassWithParameterizedOwner() throws Exception {
    Type fieldType = ParameterizedOuter.class.getField("field").getGenericType();
    assertEquals(
        fieldType, TypeToken.of(ParameterizedOuter.class).resolveType(fieldType).getType());
  }

  private interface StringIterable extends Iterable<String> {}

  public void testResolveType() {
    assertEquals(String.class, TypeToken.of(this.getClass()).resolveType(String.class).getType());
    assertEquals(
        String.class,
        TypeToken.of(StringIterable.class)
            .resolveType(Iterable.class.getTypeParameters()[0])
            .getType());
    assertEquals(
        String.class,
        TypeToken.of(StringIterable.class)
            .resolveType(Iterable.class.getTypeParameters()[0])
            .getType());
    try {
      TypeToken.of(this.getClass()).resolveType(null);
      fail();
    } catch (NullPointerException expected) {
    }
  }

  public void testConextIsParameterizedType() throws Exception {
    class Context {
      @SuppressWarnings("unused") // used by reflection
      Map<String, Integer> returningMap() {
        throw new AssertionError();
      }
    }
    Type context = Context.class.getDeclaredMethod("returningMap").getGenericReturnType();
    Type keyType = Map.class.getTypeParameters()[0];
    Type valueType = Map.class.getTypeParameters()[1];

    // context is parameterized type
    assertEquals(String.class, TypeToken.of(context).resolveType(keyType).getType());
    assertEquals(Integer.class, TypeToken.of(context).resolveType(valueType).getType());

    // context is type variable
    assertEquals(keyType, TypeToken.of(keyType).resolveType(keyType).getType());
    assertEquals(valueType, TypeToken.of(valueType).resolveType(valueType).getType());
  }

  private static final class GenericArray<T> {
    final Type t = new TypeToken<T>(getClass()) {}.getType();
    final Type array = new TypeToken<T[]>(getClass()) {}.getType();
  }

  public void testGenericArrayType() {
    GenericArray<?> genericArray = new GenericArray<>();
    assertEquals(GenericArray.class.getTypeParameters()[0], genericArray.t);
    assertEquals(Types.newArrayType(genericArray.t), genericArray.array);
  }

  public void testClassWrapper() {
    TypeToken<String> typeExpression = TypeToken.of(String.class);
    assertEquals(String.class, typeExpression.getType());
    assertEquals(String.class, typeExpression.getRawType());
  }

  private static class Red<A> {
    private class Orange {
      Class<?> getClassA() {
        return new TypeToken<A>(getClass()) {}.getRawType();
      }

      Red<A> getSelfB() {
        return Red.this;
      }
    }

    Red<A> getSelfA() {
      return this;
    }

    private class Yellow<B> extends Red<B>.Orange {
      Yellow(Red<B> red) {
        red.super();
      }

      Class<?> getClassB() {
        return new TypeToken<B>(getClass()) {}.getRawType();
      }

      Red<A> getA() {
        return getSelfA();
      }

      Red<B> getB() {
        return getSelfB();
      }
    }

    Class<?> getClassDirect() {
      return new TypeToken<A>(getClass()) {}.getRawType();
    }
  }

  public void test1() {
    Red<String> redString = new Red<String>() {};
    Red<Integer> redInteger = new Red<Integer>() {};
    assertEquals(String.class, redString.getClassDirect());
    assertEquals(Integer.class, redInteger.getClassDirect());

    Red<String>.Yellow<Integer> yellowInteger = redString.new Yellow<Integer>(redInteger) {};
    assertEquals(Integer.class, yellowInteger.getClassA());
    assertEquals(Integer.class, yellowInteger.getClassB());
    assertEquals(String.class, yellowInteger.getA().getClassDirect());
    assertEquals(Integer.class, yellowInteger.getB().getClassDirect());
  }

  public void test2() {
    Red<String> redString = new Red<>();
    Red<Integer> redInteger = new Red<>();
    Red<String>.Yellow<Integer> yellowInteger = redString.new Yellow<Integer>(redInteger) {};
    assertEquals(Integer.class, yellowInteger.getClassA());
    assertEquals(Integer.class, yellowInteger.getClassB());
  }

  private static <T> Type staticMethodWithLocalClass() {
    class MyLocalClass {
      Type getType() {
        return new TypeToken<T>(getClass()) {}.getType();
      }
    }
    return new MyLocalClass().getType();
  }

  public void testLocalClassInsideStaticMethod() {
    assertNotNull(staticMethodWithLocalClass());
  }

  public void testLocalClassInsideNonStaticMethod() {
    class MyLocalClass<T> {
      Type getType() {
        return new TypeToken<T>(getClass()) {}.getType();
      }
    }
    assertNotNull(new MyLocalClass<String>().getType());
  }

  private static <T> Type staticMethodWithAnonymousClass() {
    return new Object() {
      Type getType() {
        return new TypeToken<T>(getClass()) {}.getType();
      }
    }.getType();
  }

  public void testAnonymousClassInsideStaticMethod() {
    assertNotNull(staticMethodWithAnonymousClass());
  }

  public void testAnonymousClassInsideNonStaticMethod() {
    assertNotNull(
        new Object() {
          Type getType() {
            return new TypeToken<Object>() {}.getType();
          }
        }.getType());
  }

  public void testStaticContext() {
    assertEquals(Map.class, mapType().getRawType());
  }

  private abstract static class Holder<T> {
    Type getContentType() {
      return new TypeToken<T>(getClass()) {}.getType();
    }
  }

  public void testResolvePrimitiveArrayType() {
    assertEquals(new TypeToken<int[]>() {}.getType(), new Holder<int[]>() {}.getContentType());
    assertEquals(new TypeToken<int[][]>() {}.getType(), new Holder<int[][]>() {}.getContentType());
  }

  public void testResolveToGenericArrayType() {
    GenericArrayType arrayType =
        (GenericArrayType) new Holder<List<int[][]>[]>() {}.getContentType();
    ParameterizedType listType = (ParameterizedType) arrayType.getGenericComponentType();
    assertEquals(List.class, listType.getRawType());
    assertEquals(Types.newArrayType(int[].class), listType.getActualTypeArguments()[0]);
  }

  private abstract class WithGenericBound<A> {

    @SuppressWarnings("unused")
    public <B extends A> void withTypeVariable(List<B> list) {}

    @SuppressWarnings("unused")
    public <E extends Enum<E>> void withRecursiveBound(List<E> list) {}

    @SuppressWarnings("unused")
    public <K extends List<V>, V extends List<K>> void withMutualRecursiveBound(
        List<Map<K, V>> list) {}

    @SuppressWarnings("unused")
    void withWildcardLowerBound(List<? super A> list) {}

    @SuppressWarnings("unused")
    void withWildcardUpperBound(List<? extends A> list) {}

    Type getTargetType(String methodName) throws Exception {
      ParameterizedType parameterType =
          (ParameterizedType)
              WithGenericBound.class.getDeclaredMethod(methodName, List.class)
                  .getGenericParameterTypes()[0];
      parameterType =
          (ParameterizedType) TypeToken.of(this.getClass()).resolveType(parameterType).getType();
      return parameterType.getActualTypeArguments()[0];
    }
  }

  public void testWithGenericBoundInTypeVariable() throws Exception {
    TypeVariable<?> typeVariable =
        (TypeVariable<?>) new WithGenericBound<String>() {}.getTargetType("withTypeVariable");
    assertEquals(String.class, typeVariable.getBounds()[0]);
  }

  public void testWithRecursiveBoundInTypeVariable() throws Exception {
    TypeVariable<?> typeVariable =
        (TypeVariable<?>) new WithGenericBound<String>() {}.getTargetType("withRecursiveBound");
    assertEquals(Types.newParameterizedType(Enum.class, typeVariable), typeVariable.getBounds()[0]);
  }

  public void testWithMutualRecursiveBoundInTypeVariable() throws Exception {
    ParameterizedType paramType =
        (ParameterizedType)
            new WithGenericBound<String>() {}.getTargetType("withMutualRecursiveBound");
    TypeVariable<?> k = (TypeVariable<?>) paramType.getActualTypeArguments()[0];
    TypeVariable<?> v = (TypeVariable<?>) paramType.getActualTypeArguments()[1];
    assertEquals(Types.newParameterizedType(List.class, v), k.getBounds()[0]);
    assertEquals(Types.newParameterizedType(List.class, k), v.getBounds()[0]);
  }

  public void testWithGenericLowerBoundInWildcard() throws Exception {
    WildcardType wildcardType =
        (WildcardType) new WithGenericBound<String>() {}.getTargetType("withWildcardLowerBound");
    assertEquals(String.class, wildcardType.getLowerBounds()[0]);
  }

  public void testWithGenericUpperBoundInWildcard() throws Exception {
    WildcardType wildcardType =
        (WildcardType) new WithGenericBound<String>() {}.getTargetType("withWildcardUpperBound");
    assertEquals(String.class, wildcardType.getUpperBounds()[0]);
  }

  public void testInterfaceTypeParameterResolution() throws Exception {
    assertEquals(
        String.class,
        TypeToken.of(new TypeToken<ArrayList<String>>() {}.getType())
            .resolveType(List.class.getTypeParameters()[0])
            .getType());
  }

  private static TypeToken<Map<Object, Object>> mapType() {
    return new TypeToken<Map<Object, Object>>() {};
  }

  // Looks like recursive, but legit.
  private interface WithFalseRecursiveType<K, V> {
    WithFalseRecursiveType<List<V>, String> keyShouldNotResolveToStringList();

    WithFalseRecursiveType<List<K>, List<V>> shouldNotCauseInfiniteLoop();

    SubtypeOfWithFalseRecursiveType<List<V>, List<K>> evenSubtypeWorks();
  }

  private interface SubtypeOfWithFalseRecursiveType<K1, V1>
      extends WithFalseRecursiveType<List<K1>, List<V1>> {
    SubtypeOfWithFalseRecursiveType<V1, K1> revertKeyAndValueTypes();
  }

  public void testFalseRecursiveType_mappingOnTheSameDeclarationNotUsed() {
    Type returnType =
        genericReturnType(WithFalseRecursiveType.class, "keyShouldNotResolveToStringList");
    TypeToken<?> keyType =
        TypeToken.of(returnType).resolveType(WithFalseRecursiveType.class.getTypeParameters()[0]);
    assertEquals("java.util.List<V>", keyType.getType().toString());
  }

  public void testFalseRecursiveType_notRealRecursiveMapping() {
    Type returnType = genericReturnType(WithFalseRecursiveType.class, "shouldNotCauseInfiniteLoop");
    TypeToken<?> keyType =
        TypeToken.of(returnType).resolveType(WithFalseRecursiveType.class.getTypeParameters()[0]);
    assertEquals("java.util.List<K>", keyType.getType().toString());
  }

  public void testFalseRecursiveType_referenceOfSubtypeDoesNotConfuseMe() {
    Type returnType = genericReturnType(WithFalseRecursiveType.class, "evenSubtypeWorks");
    TypeToken<?> keyType =
        TypeToken.of(returnType).resolveType(WithFalseRecursiveType.class.getTypeParameters()[0]);
    assertEquals("java.util.List<java.util.List<V>>", keyType.getType().toString());
  }

  public void testFalseRecursiveType_intermediaryTypeMappingDoesNotConfuseMe() {
    Type returnType =
        genericReturnType(SubtypeOfWithFalseRecursiveType.class, "revertKeyAndValueTypes");
    TypeToken<?> keyType =
        TypeToken.of(returnType).resolveType(WithFalseRecursiveType.class.getTypeParameters()[0]);
    assertEquals("java.util.List<K1>", keyType.getType().toString());
  }

  private static Type genericReturnType(Class<?> cls, String methodName) {
    try {
      return cls.getMethod(methodName).getGenericReturnType();
    } catch (Exception e) {
      throw new RuntimeException(e);
    }
  }

  public void testTwoStageResolution() {
    class ForTwoStageResolution<A extends Number> {
      <B extends A> void verifyTwoStageResolution() {
        @SuppressWarnings({"unchecked", "rawtypes"})
        Type type =
            new TypeToken<B>(getClass()) {}
            // B's bound may have already resolved to something.
            // Make sure it can still further resolve when given a context.
            .where(new TypeParameter<B>() {}, (Class) Integer.class).getType();
        assertEquals(Integer.class, type);
      }
    }
    new ForTwoStageResolution<Integer>().verifyTwoStageResolution();
    new ForTwoStageResolution<Integer>() {}.verifyTwoStageResolution();
  }
}
