/*
 * Copyright 2014 Google LLC
 *
 * 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.auto.common;

import static com.google.common.truth.Truth.assertThat;
import static javax.lang.model.type.TypeKind.NONE;
import static javax.lang.model.type.TypeKind.VOID;
import static org.junit.Assert.fail;

import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.testing.EquivalenceTester;
import com.google.common.truth.Expect;
import com.google.testing.compile.CompilationRule;
import java.lang.annotation.Annotation;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.TypeParameterElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.ErrorType;
import javax.lang.model.type.PrimitiveType;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.type.TypeVisitor;
import javax.lang.model.type.WildcardType;
import javax.lang.model.util.ElementFilter;
import javax.lang.model.util.Elements;
import javax.lang.model.util.Types;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

@RunWith(JUnit4.class)
public class MoreTypesTest {
  @Rule public final CompilationRule compilationRule = new CompilationRule();
  @Rule public final Expect expect = Expect.create();

  @Test
  public void equivalence() {
    Types types = compilationRule.getTypes();
    Elements elements = compilationRule.getElements();
    TypeMirror objectType = elements.getTypeElement(Object.class.getCanonicalName()).asType();
    TypeMirror stringType = elements.getTypeElement(String.class.getCanonicalName()).asType();
    TypeElement mapElement = elements.getTypeElement(Map.class.getCanonicalName());
    TypeElement setElement = elements.getTypeElement(Set.class.getCanonicalName());
    TypeElement enumElement = elements.getTypeElement(Enum.class.getCanonicalName());
    TypeElement container = elements.getTypeElement(Container.class.getCanonicalName());
    TypeElement contained = elements.getTypeElement(Container.Contained.class.getCanonicalName());
    TypeElement funkyBounds = elements.getTypeElement(FunkyBounds.class.getCanonicalName());
    TypeElement funkyBounds2 = elements.getTypeElement(FunkyBounds2.class.getCanonicalName());
    TypeElement funkierBounds = elements.getTypeElement(FunkierBounds.class.getCanonicalName());
    TypeMirror funkyBoundsVar = ((DeclaredType) funkyBounds.asType()).getTypeArguments().get(0);
    TypeMirror funkyBounds2Var = ((DeclaredType) funkyBounds2.asType()).getTypeArguments().get(0);
    TypeMirror funkierBoundsVar = ((DeclaredType) funkierBounds.asType()).getTypeArguments().get(0);
    DeclaredType mapOfObjectToObjectType =
        types.getDeclaredType(mapElement, objectType, objectType);
    TypeMirror mapType = mapElement.asType();
    DeclaredType setOfSetOfObject =
        types.getDeclaredType(setElement, types.getDeclaredType(setElement, objectType));
    DeclaredType setOfSetOfString =
        types.getDeclaredType(setElement, types.getDeclaredType(setElement, stringType));
    DeclaredType setOfSetOfSetOfObject = types.getDeclaredType(setElement, setOfSetOfObject);
    DeclaredType setOfSetOfSetOfString = types.getDeclaredType(setElement, setOfSetOfString);
    WildcardType wildcard = types.getWildcardType(null, null);
    DeclaredType containerOfObject = types.getDeclaredType(container, objectType);
    DeclaredType containerOfString = types.getDeclaredType(container, stringType);
    TypeMirror containedInObject = types.asMemberOf(containerOfObject, contained);
    TypeMirror containedInString = types.asMemberOf(containerOfString, contained);
    EquivalenceTester<TypeMirror> tester = EquivalenceTester.<TypeMirror>of(MoreTypes.equivalence())
        .addEquivalenceGroup(types.getNullType())
        .addEquivalenceGroup(types.getNoType(NONE))
        .addEquivalenceGroup(types.getNoType(VOID))
        .addEquivalenceGroup(objectType)
        .addEquivalenceGroup(stringType)
        .addEquivalenceGroup(containedInObject)
        .addEquivalenceGroup(containedInString)
        .addEquivalenceGroup(funkyBounds.asType())
        .addEquivalenceGroup(funkyBounds2.asType())
        .addEquivalenceGroup(funkierBounds.asType())
        .addEquivalenceGroup(funkyBoundsVar, funkyBounds2Var)
        .addEquivalenceGroup(funkierBoundsVar)
        // Enum<E extends Enum<E>>
        .addEquivalenceGroup(enumElement.asType())
        // Map<K, V>
        .addEquivalenceGroup(mapType)
        .addEquivalenceGroup(mapOfObjectToObjectType)
        // Map<?, ?>
        .addEquivalenceGroup(types.getDeclaredType(mapElement, wildcard, wildcard))
        // Map
        .addEquivalenceGroup(types.erasure(mapType), types.erasure(mapOfObjectToObjectType))
        .addEquivalenceGroup(types.getDeclaredType(mapElement, objectType, stringType))
        .addEquivalenceGroup(types.getDeclaredType(mapElement, stringType, objectType))
        .addEquivalenceGroup(types.getDeclaredType(mapElement, stringType, stringType))
        .addEquivalenceGroup(setOfSetOfObject)
        .addEquivalenceGroup(setOfSetOfString)
        .addEquivalenceGroup(setOfSetOfSetOfObject)
        .addEquivalenceGroup(setOfSetOfSetOfString)
        .addEquivalenceGroup(wildcard)
        // ? extends Object
        .addEquivalenceGroup(types.getWildcardType(objectType, null))
        // ? extends String
        .addEquivalenceGroup(types.getWildcardType(stringType, null))
        // ? super String
        .addEquivalenceGroup(types.getWildcardType(null, stringType))
        // Map<String, Map<String, Set<Object>>>
        .addEquivalenceGroup(types.getDeclaredType(mapElement, stringType,
            types.getDeclaredType(mapElement, stringType,
                types.getDeclaredType(setElement, objectType))))
        .addEquivalenceGroup(FAKE_ERROR_TYPE)
        ;

    for (TypeKind kind : TypeKind.values()) {
      if (kind.isPrimitive()) {
        PrimitiveType primitiveType = types.getPrimitiveType(kind);
        TypeMirror boxedPrimitiveType = types.boxedClass(primitiveType).asType();
        tester.addEquivalenceGroup(primitiveType, types.unboxedType(boxedPrimitiveType));
        tester.addEquivalenceGroup(boxedPrimitiveType);
        tester.addEquivalenceGroup(types.getArrayType(primitiveType));
        tester.addEquivalenceGroup(types.getArrayType(boxedPrimitiveType));
      }
    }

    ImmutableSet<Class<?>> testClasses = ImmutableSet.of(
        ExecutableElementsGroupA.class,
        ExecutableElementsGroupB.class,
        ExecutableElementsGroupC.class,
        ExecutableElementsGroupD.class,
        ExecutableElementsGroupE.class);
    for (Class<?> testClass : testClasses) {
      ImmutableList<TypeMirror> equivalenceGroup = FluentIterable.from(
          elements.getTypeElement(testClass.getCanonicalName()).getEnclosedElements())
              .transform(new Function<Element, TypeMirror>() {
                @Override public TypeMirror apply(Element input) {
                  return input.asType();
                }
              })
              .toList();
      tester.addEquivalenceGroup(equivalenceGroup);
    }

    tester.test();
  }

  @SuppressWarnings("unused")
  private static final class ExecutableElementsGroupA {
    ExecutableElementsGroupA() {}
    void a() {}
    public static void b() {}
  }

  @SuppressWarnings("unused")
  private static final class ExecutableElementsGroupB {
    ExecutableElementsGroupB(String s) {}
    void a(String s) {}
    public static void b(String s) {}
  }

  @SuppressWarnings("unused")
  private static final class ExecutableElementsGroupC {
    ExecutableElementsGroupC() throws Exception {}
    void a() throws Exception {}
    public static void b() throws Exception {}
  }

  @SuppressWarnings("unused")
  private static final class ExecutableElementsGroupD {
    ExecutableElementsGroupD() throws RuntimeException {}
    void a() throws RuntimeException {}
    public static void b() throws RuntimeException {}
  }

  @SuppressWarnings("unused")
  private static final class ExecutableElementsGroupE {
    <T> ExecutableElementsGroupE() {}
    <T> void a() {}
    public static <T> void b() {}
  }

  @SuppressWarnings("unused")
  private static final class Container<T> {
    private final class Contained {}
  }

  @SuppressWarnings("unused")
  private static final class FunkyBounds<T extends Number & Comparable<T>> {}

  @SuppressWarnings("unused")
  private static final class FunkyBounds2<T extends Number & Comparable<T>> {}

  @SuppressWarnings("unused")
  private static final class FunkierBounds<T extends Number & Comparable<T> & Cloneable> {}

  @Test public void testReferencedTypes() {
    Elements elements = compilationRule.getElements();
    TypeElement testDataElement = elements
        .getTypeElement(ReferencedTypesTestData.class.getCanonicalName());
    ImmutableMap<String, VariableElement> fieldIndex =
        FluentIterable.from(ElementFilter.fieldsIn(testDataElement.getEnclosedElements()))
            .uniqueIndex(new Function<VariableElement, String>() {
              @Override public String apply(VariableElement input) {
                return input.getSimpleName().toString();
              }
            });

    TypeElement objectElement =
        elements.getTypeElement(Object.class.getCanonicalName());
    TypeElement stringElement =
        elements.getTypeElement(String.class.getCanonicalName());
    TypeElement integerElement =
        elements.getTypeElement(Integer.class.getCanonicalName());
    TypeElement setElement =
        elements.getTypeElement(Set.class.getCanonicalName());
    TypeElement mapElement =
        elements.getTypeElement(Map.class.getCanonicalName());
    TypeElement charSequenceElement =
        elements.getTypeElement(CharSequence.class.getCanonicalName());

    assertThat(MoreTypes.referencedTypes(fieldIndex.get("f1").asType()))
        .containsExactly(objectElement);
    assertThat(MoreTypes.referencedTypes(fieldIndex.get("f2").asType()))
        .containsExactly(setElement, stringElement);
    assertThat(MoreTypes.referencedTypes(fieldIndex.get("f3").asType()))
        .containsExactly(mapElement, stringElement, objectElement);
    assertThat(MoreTypes.referencedTypes(fieldIndex.get("f4").asType()))
        .containsExactly(integerElement);
    assertThat(MoreTypes.referencedTypes(fieldIndex.get("f5").asType()))
        .containsExactly(setElement);
    assertThat(MoreTypes.referencedTypes(fieldIndex.get("f6").asType()))
        .containsExactly(setElement, charSequenceElement);
    assertThat(MoreTypes.referencedTypes(fieldIndex.get("f7").asType()))
        .containsExactly(mapElement, stringElement, setElement, charSequenceElement);
    assertThat(MoreTypes.referencedTypes(fieldIndex.get("f8").asType()))
        .containsExactly(stringElement);
    assertThat(MoreTypes.referencedTypes(fieldIndex.get("f9").asType()))
        .containsExactly(stringElement);
    assertThat(MoreTypes.referencedTypes(fieldIndex.get("f10").asType())).isEmpty();
    assertThat(MoreTypes.referencedTypes(fieldIndex.get("f11").asType())).isEmpty();
    assertThat(MoreTypes.referencedTypes(fieldIndex.get("f12").asType()))
        .containsExactly(setElement, stringElement);
  }

  @SuppressWarnings("unused") // types used in compiler tests
  private static final class ReferencedTypesTestData {
    Object f1;
    Set<String> f2;
    Map<String, Object> f3;
    Integer f4;
    Set<?> f5;
    Set<? extends CharSequence> f6;
    Map<String, Set<? extends CharSequence>> f7;
    String[] f8;
    String[][] f9;
    int f10;
    int[] f11;
    Set<? super String> f12;
  }

  private static class Parent<T> {}
  private static class ChildA extends Parent<Number> {}
  private static class ChildB extends Parent<String> {}
  private static class GenericChild<T> extends Parent<T> {}
  private interface InterfaceType {}

  @Test
  public void asElement_throws() {
    TypeMirror javaDotLang =
        compilationRule.getElements().getPackageElement("java.lang").asType();
    try {
      MoreTypes.asElement(javaDotLang);
      fail();
    } catch (IllegalArgumentException expected) {}

  }

  @Test
  public void asElement() {
    Elements elements = compilationRule.getElements();
    TypeElement stringElement = elements.getTypeElement("java.lang.String");
    assertThat(MoreTypes.asElement(stringElement.asType())).isEqualTo(stringElement);
    TypeParameterElement setParameterElement = Iterables.getOnlyElement(
        compilationRule.getElements().getTypeElement("java.util.Set").getTypeParameters());
    assertThat(MoreTypes.asElement(setParameterElement.asType())).isEqualTo(setParameterElement);
    // we don't test error types because those are very hard to get predictably
  }

  @Test
  public void testNonObjectSuperclass() {
    Types types = compilationRule.getTypes();
    Elements elements = compilationRule.getElements();
    TypeMirror numberType = elements.getTypeElement(Number.class.getCanonicalName()).asType();
    TypeMirror stringType = elements.getTypeElement(String.class.getCanonicalName()).asType();
    TypeMirror integerType = elements.getTypeElement(Integer.class.getCanonicalName()).asType();
    TypeElement parent = elements.getTypeElement(Parent.class.getCanonicalName());
    TypeElement childA = elements.getTypeElement(ChildA.class.getCanonicalName());
    TypeElement childB = elements.getTypeElement(ChildB.class.getCanonicalName());
    TypeElement genericChild = elements.getTypeElement(GenericChild.class.getCanonicalName());
    TypeMirror genericChildOfNumber = types.getDeclaredType(genericChild, numberType);
    TypeMirror genericChildOfInteger = types.getDeclaredType(genericChild, integerType);
    TypeMirror objectType =
        elements.getTypeElement(Object.class.getCanonicalName()).asType();
    TypeMirror interfaceType =
        elements.getTypeElement(InterfaceType.class.getCanonicalName()).asType();

    assertThat(MoreTypes.nonObjectSuperclass(types, elements, (DeclaredType) objectType))
        .isAbsent();
    assertThat(MoreTypes.nonObjectSuperclass(types, elements, (DeclaredType) interfaceType))
        .isAbsent();
    assertThat(MoreTypes.nonObjectSuperclass(types, elements, (DeclaredType) parent.asType()))
        .isAbsent();

    Optional<DeclaredType> parentOfChildA =
        MoreTypes.nonObjectSuperclass(types, elements, (DeclaredType) childA.asType());
    Optional<DeclaredType> parentOfChildB =
        MoreTypes.nonObjectSuperclass(types, elements, (DeclaredType) childB.asType());
    Optional<DeclaredType> parentOfGenericChild =
        MoreTypes.nonObjectSuperclass(types, elements, (DeclaredType) genericChild.asType());
    Optional<DeclaredType> parentOfGenericChildOfNumber =
        MoreTypes.nonObjectSuperclass(types, elements, (DeclaredType) genericChildOfNumber);
    Optional<DeclaredType> parentOfGenericChildOfInteger =
        MoreTypes.nonObjectSuperclass(types, elements, (DeclaredType) genericChildOfInteger);

    EquivalenceTester<TypeMirror> tester = EquivalenceTester.<TypeMirror>of(MoreTypes.equivalence())
          .addEquivalenceGroup(parentOfChildA.get(),
              types.getDeclaredType(parent, numberType),
              parentOfGenericChildOfNumber.get())
          .addEquivalenceGroup(parentOfChildB.get(), types.getDeclaredType(parent, stringType))
          .addEquivalenceGroup(parentOfGenericChild.get(), parent.asType())
          .addEquivalenceGroup(parentOfGenericChildOfInteger.get(),
              types.getDeclaredType(parent, integerType));

    tester.test();
  }
  
  @Test
  public void testAsMemberOf_variableElement() {
    Types types = compilationRule.getTypes();
    Elements elements = compilationRule.getElements();
    TypeMirror numberType = elements.getTypeElement(Number.class.getCanonicalName()).asType();
    TypeMirror stringType = elements.getTypeElement(String.class.getCanonicalName()).asType();
    TypeMirror integerType = elements.getTypeElement(Integer.class.getCanonicalName()).asType();

    TypeElement paramsElement = elements.getTypeElement(Params.class.getCanonicalName());
    VariableElement tParam = Iterables.getOnlyElement(Iterables.getOnlyElement(
        ElementFilter.methodsIn(paramsElement.getEnclosedElements())).getParameters());
    VariableElement tField =
        Iterables.getOnlyElement(ElementFilter.fieldsIn(paramsElement.getEnclosedElements())); 
    
    DeclaredType numberParams =
        (DeclaredType) elements.getTypeElement(NumberParams.class.getCanonicalName()).asType();
    DeclaredType stringParams =
        (DeclaredType) elements.getTypeElement(StringParams.class.getCanonicalName()).asType();
    TypeElement genericParams = elements.getTypeElement(GenericParams.class.getCanonicalName());
    DeclaredType genericParamsOfNumber = types.getDeclaredType(genericParams, numberType);
    DeclaredType genericParamsOfInteger = types.getDeclaredType(genericParams, integerType);
    
    TypeMirror fieldOfNumberParams = MoreTypes.asMemberOf(types, numberParams, tField);
    TypeMirror paramOfNumberParams = MoreTypes.asMemberOf(types, numberParams, tParam);
    TypeMirror fieldOfStringParams = MoreTypes.asMemberOf(types, stringParams, tField);
    TypeMirror paramOfStringParams = MoreTypes.asMemberOf(types, stringParams, tParam);
    TypeMirror fieldOfGenericOfNumber = MoreTypes.asMemberOf(types, genericParamsOfNumber, tField);
    TypeMirror paramOfGenericOfNumber = MoreTypes.asMemberOf(types, genericParamsOfNumber, tParam);
    TypeMirror fieldOfGenericOfInteger =
        MoreTypes.asMemberOf(types, genericParamsOfInteger, tField);
    TypeMirror paramOfGenericOfInteger =
        MoreTypes.asMemberOf(types, genericParamsOfInteger, tParam);

    EquivalenceTester<TypeMirror> tester = EquivalenceTester.<TypeMirror>of(MoreTypes.equivalence())
        .addEquivalenceGroup(fieldOfNumberParams, paramOfNumberParams, fieldOfGenericOfNumber,
            paramOfGenericOfNumber, numberType)
        .addEquivalenceGroup(fieldOfStringParams, paramOfStringParams, stringType)
        .addEquivalenceGroup(fieldOfGenericOfInteger, paramOfGenericOfInteger, integerType);
    tester.test();
  }
  
  private static class Params<T> {
    @SuppressWarnings("unused") T t;
    @SuppressWarnings("unused") void add(T t) {}
  }
  private static class NumberParams extends Params<Number> {}
  private static class StringParams extends Params<String> {}
  private static class GenericParams<T> extends Params<T> {}

  private static final ErrorType FAKE_ERROR_TYPE = new ErrorType() {
    @Override
    public TypeKind getKind() {
      return TypeKind.ERROR;
    }

    @Override
    public <R, P> R accept(TypeVisitor<R, P> v, P p) {
      return v.visitError(this, p);
    }

    @Override
    public List<? extends TypeMirror> getTypeArguments() {
      return ImmutableList.of();
    }

    @Override
    public TypeMirror getEnclosingType() {
      return null;
    }

    @Override
    public Element asElement() {
      return null;
    }

    // JDK8 Compatibility:

    public <A extends Annotation> A[] getAnnotationsByType(Class<A> annotationType) {
      return null;
    }

    public <A extends Annotation> A getAnnotation(Class<A> annotationType) {
      return null;
    }

    public List<? extends AnnotationMirror> getAnnotationMirrors() {
      return null;
    }
  };

  @Test
  public void testIsConversionFromObjectUnchecked_yes() {
    Elements elements = compilationRule.getElements();
    TypeElement unchecked = elements.getTypeElement(Unchecked.class.getCanonicalName());
    for (VariableElement field : ElementFilter.fieldsIn(unchecked.getEnclosedElements())) {
      TypeMirror type = field.asType();
      expect
          .withMessage("Casting to %s is unchecked", type)
          .that(MoreTypes.isConversionFromObjectUnchecked(type))
          .isTrue();
    }
  }

  @Test
  public void testIsConversionFromObjectUnchecked_no() {
    Elements elements = compilationRule.getElements();
    TypeElement notUnchecked = elements.getTypeElement(NotUnchecked.class.getCanonicalName());
    for (VariableElement field : ElementFilter.fieldsIn(notUnchecked.getEnclosedElements())) {
      TypeMirror type = field.asType();
      expect
          .withMessage("Casting to %s is not unchecked", type)
          .that(MoreTypes.isConversionFromObjectUnchecked(type))
          .isFalse();
    }
  }

  // The type of every field here is such that casting to it provokes an "unchecked" warning.
  @SuppressWarnings("unused")
  private static class Unchecked<T> {
    private List<String> listOfString;
    private List<? extends CharSequence> listOfExtendsCharSequence;
    private List<? super CharSequence> listOfSuperCharSequence;
    private List<T> listOfT;
    private List<T[]> listOfArrayOfT;
    private T t;
    private T[] arrayOfT;
    private List<T>[] arrayOfListOfT;
    private Map<?, String> mapWildcardToString;
    private Map<String, ?> mapStringToWildcard;
  }

  // The type of every field here is such that casting to it doesn't provoke an "unchecked" warning.
  @SuppressWarnings("unused")
  private static class NotUnchecked {
    private String string;
    private int integer;
    private String[] arrayOfString;
    private int[] arrayOfInt;
    private Thread.State threadStateEnum;
    private List<?> listOfWildcard;
    private List<? extends Object> listOfWildcardExtendsObject;
    private Map<?, ?> mapWildcardToWildcard;
  }
}
