/**
 * Copyright (C) 2006 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 com.google.common.collect.ImmutableList;
import com.google.inject.util.Types;

import junit.framework.TestCase;

import java.io.IOException;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.List;

/**
 * @author crazybob@google.com (Bob Lee)
 */
public class TypeLiteralTest extends TestCase {

  public void testWithParameterizedType() {
    TypeLiteral<List<String>> a = new TypeLiteral<List<String>>() {};
    TypeLiteral<List<String>> b = new TypeLiteral<List<String>>(
        Types.listOf(String.class)) {};
    assertEqualsBothWays(a, b);
  }

  public void testEquality() {
    TypeLiteral<List<String>> t1 = new TypeLiteral<List<String>>() {};
    TypeLiteral<List<String>> t2 = new TypeLiteral<List<String>>() {};
    TypeLiteral<List<Integer>> t3 = new TypeLiteral<List<Integer>>() {};
    TypeLiteral<String> t4 = new TypeLiteral<String>() {};

    assertEqualsBothWays(t1, t2);

    assertFalse(t2.equals(t3));
    assertFalse(t3.equals(t2));

    assertFalse(t2.equals(t4));
    assertFalse(t4.equals(t2));

    TypeLiteral<String> t5 = TypeLiteral.get(String.class);
    assertEqualsBothWays(t4, t5);
  }

  public List<? extends CharSequence> wildcardExtends;

  public void testWithWildcardType() throws NoSuchFieldException, IOException {
    TypeLiteral<?> a = TypeLiteral.get(getClass().getField("wildcardExtends").getGenericType());
    TypeLiteral<?> b = TypeLiteral.get(Types.listOf(Types.subtypeOf(CharSequence.class)));
    TypeLiteral<?> c = new TypeLiteral<List<? extends CharSequence>>() {};
    assertEqualsBothWays(a, b);
    assertEqualsBothWays(b, c);
    assertEquals("java.util.List<? extends java.lang.CharSequence>", a.toString());
    assertEquals("java.util.List<? extends java.lang.CharSequence>", b.toString());
    assertEquals("java.util.List<? extends java.lang.CharSequence>", c.toString());
    assertNotSerializable(a);
    assertNotSerializable(b);
    assertNotSerializable(c);
  }

  public void testMissingTypeParameter() {
    try {
      new TypeLiteral() {};
      fail();
    } catch (RuntimeException e) { /* expected */ }
  }

  public void testTypesInvolvingArraysForEquality() {
    TypeLiteral<String[]> stringArray = new TypeLiteral<String[]>() {};
    assertEquals(stringArray, new TypeLiteral<String[]>() {});

    TypeLiteral<List<String[]>> listOfStringArray
        = new TypeLiteral<List<String[]>>() {};
    assertEquals(listOfStringArray, new TypeLiteral<List<String[]>>() {});
  }

  public void testEqualityOfGenericArrayAndClassArray() {
    TypeLiteral<String[]> arrayAsClass = TypeLiteral.get(String[].class);
    TypeLiteral<String[]> arrayAsType = new TypeLiteral<String[]>() {};
    assertEquals(arrayAsClass, arrayAsType);
  }

  public void testEqualityOfMultidimensionalGenericArrayAndClassArray() {
    TypeLiteral<String[][][]> arrayAsClass = TypeLiteral.get(String[][][].class);
    TypeLiteral<String[][][]> arrayAsType = new TypeLiteral<String[][][]>() {};
    assertEquals(arrayAsClass, arrayAsType);
  }

  public void testTypeLiteralsMustHaveRawTypes() {
    try {
      TypeLiteral.get(Types.subtypeOf(Runnable.class));
      fail();
    } catch (IllegalArgumentException expected) {
      Asserts.assertContains(expected.getMessage(), "Expected a Class, ParameterizedType, or "
          + "GenericArrayType, but <? extends java.lang.Runnable> is of type "
          + "com.google.inject.internal.MoreTypes$WildcardTypeImpl");
    }
  }

  /**
   * Unlike Key, TypeLiteral retains full type information and differentiates
   * between {@code int.class} and {@code Integer.class}.
   */
  public void testDifferentiationBetweenWrappersAndPrimitives() {
    Class[] primitives = new Class[] {
        boolean.class, byte.class, short.class, int.class, long.class,
        float.class, double.class, char.class, void.class
    };
    Class[] wrappers = new Class[] {
        Boolean.class, Byte.class, Short.class, Integer.class, Long.class,
        Float.class, Double.class, Character.class, Void.class
    };

    for (int t = 0; t < primitives.length; t++) {
      @SuppressWarnings("unchecked")
      TypeLiteral primitiveTl = TypeLiteral.get(primitives[t]);
      @SuppressWarnings("unchecked")
      TypeLiteral wrapperTl = TypeLiteral.get(wrappers[t]);

      assertFalse(primitiveTl.equals(wrapperTl));
      assertEquals(primitives[t], primitiveTl.getType());
      assertEquals(wrappers[t], wrapperTl.getType());
      assertEquals(primitives[t], primitiveTl.getRawType());
      assertEquals(wrappers[t], wrapperTl.getRawType());
    }
  }

  public void testSerialization() throws IOException {
    assertNotSerializable(new TypeLiteral<List<String>>() {});
  }

  public void testTypeVariableWithNoBound() {
    TypeVariable<Class<HasTypeParameters>>[] typeVariables
        = HasTypeParameters.class.getTypeParameters();

    TypeLiteral<?> aTl = TypeLiteral.get(typeVariables[0]);
    assertEquals(Object.class, aTl.getRawType());
    assertEquals("A", aTl.toString());
    TypeVariable<?> aTv = (TypeVariable) aTl.getType();
    assertEquals(HasTypeParameters.class, aTv.getGenericDeclaration());
    assertEquals("A", aTv.getName());
    assertEquals(ImmutableList.<Type>of(Object.class), ImmutableList.copyOf(aTv.getBounds()));
    assertEquals("A", aTv.toString());
    assertEqualsBothWays(aTl, TypeLiteral.get(HasTypeParameters.class.getTypeParameters()[0]));
  }

  public void testTypeVariablesWithSingleBound() {
    TypeVariable<Class<HasTypeParameters>>[] typeVariables
        = HasTypeParameters.class.getTypeParameters();

    TypeLiteral<?> cTl = TypeLiteral.get(typeVariables[2]);
    assertEquals(Object.class, cTl.getRawType());
    assertEquals("C", cTl.toString());
    TypeVariable<?> cTv = (TypeVariable) cTl.getType();
    assertEquals(HasTypeParameters.class, cTv.getGenericDeclaration());
    assertEquals("C", cTv.getName());
    assertEquals(ImmutableList.<Type>of(Runnable.class), ImmutableList.copyOf(cTv.getBounds()));
    assertEquals("C", cTv.toString());
    assertEqualsBothWays(cTl, TypeLiteral.get(HasTypeParameters.class.getTypeParameters()[2]));
  }

  public void testTypeVariableWithMultipleBounds() {
    TypeVariable<Class<HasTypeParameters>>[] typeVariables
        = HasTypeParameters.class.getTypeParameters();

    TypeLiteral<?> bTl = TypeLiteral.get(typeVariables[1]);
    assertEquals(Object.class, bTl.getRawType());
    assertEquals("B", bTl.toString());
    TypeVariable<?> bTv = (TypeVariable) bTl.getType();
    assertEquals(HasTypeParameters.class, bTv.getGenericDeclaration());
    assertEquals("B", bTv.getName());
    assertEquals(ImmutableList.<Type>of(Types.listOf(typeVariables[0]), Runnable.class),
        ImmutableList.copyOf(bTv.getBounds()));
    assertEquals("B", bTv.toString());
    assertEqualsBothWays(bTl, TypeLiteral.get(HasTypeParameters.class.getTypeParameters()[1]));
  }

  class HasTypeParameters<A, B extends List<A> & Runnable, C extends Runnable> {
    A a; B b; C c;
  }
}
