/**
 * 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.spi;

import static com.google.common.collect.Iterables.getOnlyElement;
import static com.google.inject.Asserts.assertContains;
import static com.google.inject.Asserts.assertEqualsBothWays;
import static com.google.inject.Asserts.assertNotSerializable;
import static com.google.inject.name.Names.named;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.inject.ConfigurationException;
import com.google.inject.Inject;
import com.google.inject.Key;
import com.google.inject.TypeLiteral;
import com.google.inject.internal.ErrorsException;
import com.google.inject.name.Named;
import com.google.inject.spi.InjectionPoint.Signature;

import junit.framework.Assert;
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.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;

/**
 * @author jessewilson@google.com (Jesse Wilson)
 */
public class InjectionPointTest extends TestCase {

  public @Inject @Named("a") String foo;
  public @Inject void bar(@Named("b") String param) {}

  public static class Constructable {
    @Inject public Constructable(@Named("c") String param) {}
  }

  public void testFieldInjectionPoint() throws NoSuchFieldException, IOException, ErrorsException {
    TypeLiteral<?> typeLiteral = TypeLiteral.get(getClass());
    Field fooField = getClass().getField("foo");

    InjectionPoint injectionPoint = new InjectionPoint(typeLiteral, fooField, false);
    assertSame(fooField, injectionPoint.getMember());
    assertFalse(injectionPoint.isOptional());
    assertEquals(getClass().getName() + ".foo", injectionPoint.toString());
    assertEqualsBothWays(injectionPoint, new InjectionPoint(typeLiteral, fooField, false));
    assertNotSerializable(injectionPoint);

    Dependency<?> dependency = getOnlyElement(injectionPoint.getDependencies());
    assertEquals("Key[type=java.lang.String, annotation=@com.google.inject.name.Named(value=a)]@"
        + getClass().getName() + ".foo", dependency.toString());
    assertEquals(fooField, dependency.getInjectionPoint().getMember());
    assertEquals(-1, dependency.getParameterIndex());
    Assert.assertEquals(Key.get(String.class, named("a")), dependency.getKey());
    assertEquals(false, dependency.isNullable());
    assertNotSerializable(dependency);
    assertEqualsBothWays(dependency,
        getOnlyElement(new InjectionPoint(typeLiteral, fooField, false).getDependencies()));
  }

  public void testMethodInjectionPoint() throws Exception {
    TypeLiteral<?> typeLiteral = TypeLiteral.get(getClass());

    Method barMethod = getClass().getMethod("bar", String.class);
    InjectionPoint injectionPoint = new InjectionPoint(typeLiteral, barMethod, false);
    assertSame(barMethod, injectionPoint.getMember());
    assertFalse(injectionPoint.isOptional());
    assertEquals(getClass().getName() + ".bar()", injectionPoint.toString());
    assertEqualsBothWays(injectionPoint, new InjectionPoint(typeLiteral, barMethod, false));
    assertNotSerializable(injectionPoint);

    Dependency<?> dependency = getOnlyElement(injectionPoint.getDependencies());
    assertEquals("Key[type=java.lang.String, annotation=@com.google.inject.name.Named(value=b)]@"
        + getClass().getName() + ".bar()[0]", dependency.toString());
    assertEquals(barMethod, dependency.getInjectionPoint().getMember());
    assertEquals(0, dependency.getParameterIndex());
    assertEquals(Key.get(String.class, named("b")), dependency.getKey());
    assertEquals(false, dependency.isNullable());
    assertNotSerializable(dependency);
    assertEqualsBothWays(dependency,
        getOnlyElement(new InjectionPoint(typeLiteral, barMethod, false).getDependencies()));
  }

  public void testConstructorInjectionPoint() throws NoSuchMethodException, IOException,
      ErrorsException {
    TypeLiteral<?> typeLiteral = TypeLiteral.get(Constructable.class);

    Constructor<?> constructor = Constructable.class.getConstructor(String.class);
    InjectionPoint injectionPoint = new InjectionPoint(typeLiteral, constructor);
    assertSame(constructor, injectionPoint.getMember());
    assertFalse(injectionPoint.isOptional());
    assertEquals(Constructable.class.getName() + ".<init>()", injectionPoint.toString());
    assertEqualsBothWays(injectionPoint, new InjectionPoint(typeLiteral, constructor));
    assertNotSerializable(injectionPoint);

    Dependency<?> dependency = getOnlyElement(injectionPoint.getDependencies());
    assertEquals("Key[type=java.lang.String, annotation=@com.google.inject.name.Named(value=c)]@"
        + Constructable.class.getName() + ".<init>()[0]", dependency.toString());
    assertEquals(constructor, dependency.getInjectionPoint().getMember());
    assertEquals(0, dependency.getParameterIndex());
    assertEquals(Key.get(String.class, named("c")), dependency.getKey());
    assertEquals(false, dependency.isNullable());
    assertNotSerializable(dependency);
    assertEqualsBothWays(dependency,
        getOnlyElement(new InjectionPoint(typeLiteral, constructor).getDependencies()));
  }

  public void testUnattachedDependency() throws IOException {
    Dependency<String> dependency = Dependency.get(Key.get(String.class, named("d")));
    assertEquals("Key[type=java.lang.String, annotation=@com.google.inject.name.Named(value=d)]",
        dependency.toString());
    assertNull(dependency.getInjectionPoint());
    assertEquals(-1, dependency.getParameterIndex());
    assertEquals(Key.get(String.class, named("d")), dependency.getKey());
    assertEquals(true, dependency.isNullable());
    assertNotSerializable(dependency);
    assertEqualsBothWays(dependency, Dependency.get(Key.get(String.class, named("d"))));
  }

  public void testForConstructor() throws NoSuchMethodException {
    Constructor<HashSet> constructor = HashSet.class.getConstructor();
    TypeLiteral<HashSet<String>> hashSet = new TypeLiteral<HashSet<String>>() {};

    InjectionPoint injectionPoint = InjectionPoint.forConstructor(constructor, hashSet);
    assertSame(constructor, injectionPoint.getMember());
    assertEquals(ImmutableList.<Dependency>of(), injectionPoint.getDependencies());
    assertFalse(injectionPoint.isOptional());

    try {
      InjectionPoint.forConstructor(constructor, new TypeLiteral<LinkedHashSet<String>>() {});
    } catch (ConfigurationException expected) {
      assertContains(expected.getMessage(), "java.util.LinkedHashSet<java.lang.String>",
          " does not define java.util.HashSet.<init>()",
          "  while locating java.util.LinkedHashSet<java.lang.String>");
    }

    try {
      InjectionPoint.forConstructor((Constructor) constructor, new TypeLiteral<Set<String>>() {});
    } catch (ConfigurationException expected) {
      assertContains(expected.getMessage(), "java.util.Set<java.lang.String>",
          " does not define java.util.HashSet.<init>()",
          "  while locating java.util.Set<java.lang.String>");
    }
  }

  public void testForConstructorOf() {
    InjectionPoint injectionPoint = InjectionPoint.forConstructorOf(Constructable.class);
    assertEquals(Constructable.class.getName() + ".<init>()", injectionPoint.toString());
  }

  public void testAddForInstanceMethodsAndFields() throws Exception {
    Method instanceMethod = HasInjections.class.getMethod("instanceMethod", String.class);
    Field instanceField = HasInjections.class.getField("instanceField");

    TypeLiteral<HasInjections> type = TypeLiteral.get(HasInjections.class);
    assertEquals(ImmutableSet.of(
        new InjectionPoint(type, instanceMethod, false),
        new InjectionPoint(type, instanceField, false)),
        InjectionPoint.forInstanceMethodsAndFields(HasInjections.class));
  }

  public void testAddForStaticMethodsAndFields() throws Exception {
    Method staticMethod = HasInjections.class.getMethod("staticMethod", String.class);
    Field staticField = HasInjections.class.getField("staticField");

    Set<InjectionPoint> injectionPoints = InjectionPoint.forStaticMethodsAndFields(
        HasInjections.class);
    assertEquals(ImmutableSet.of(
        new InjectionPoint(TypeLiteral.get(HasInjections.class), staticMethod, false),
        new InjectionPoint(TypeLiteral.get(HasInjections.class), staticField, false)),
        injectionPoints);
  }

  static class HasInjections {
    @Inject public static void staticMethod(@Named("a") String a) {}
    @Inject @Named("c") public static String staticField;
    @Inject public void instanceMethod(@Named("d") String d) {}
    @Inject @Named("f") public String instanceField;
  }

  public void testAddForParameterizedInjections() {
    TypeLiteral<?> type = new TypeLiteral<ParameterizedInjections<String>>() {};

    InjectionPoint constructor = InjectionPoint.forConstructorOf(type);
    assertEquals(new Key<Map<String, String>>() {},
        getOnlyElement(constructor.getDependencies()).getKey());

    InjectionPoint field = getOnlyElement(InjectionPoint.forInstanceMethodsAndFields(type));
    assertEquals(new Key<Set<String>>() {}, getOnlyElement(field.getDependencies()).getKey());
  }

  static class ParameterizedInjections<T> {
    @Inject Set<T> setOfTees;
    @Inject public ParameterizedInjections(Map<T, T> map) {}
  }

  public void testSignature() throws Exception {
    Signature fooA = new Signature(Foo.class.getDeclaredMethod(
        "a", String.class, int.class));
    Signature fooB = new Signature(Foo.class.getDeclaredMethod("b"));
    Signature barA = new Signature(Bar.class.getDeclaredMethod(
        "a", String.class, int.class));
    Signature barB = new Signature(Bar.class.getDeclaredMethod("b"));

    assertEquals(fooA.hashCode(), barA.hashCode());
    assertEquals(fooB.hashCode(), barB.hashCode());
    assertEquals(fooA, barA);
    assertEquals(fooB, barB);
  }

  static class Foo {
    void a(String s, int i) {}
    int b() {
      return 0;
    }
  }
  static class Bar {
    public void a(String s, int i) {}
    void b() {}
  }
  
  public void testOverrideBehavior() {
    Set<InjectionPoint> points;

    points = InjectionPoint.forInstanceMethodsAndFields(Super.class);
    assertEquals(points.toString(), 6, points.size());
    assertPoints(points, Super.class, "atInject", "gInject", "privateAtAndPublicG",
        "privateGAndPublicAt", "atFirstThenG", "gFirstThenAt");

    points = InjectionPoint.forInstanceMethodsAndFields(Sub.class);
    assertEquals(points.toString(), 7, points.size());
    // Superclass will always have is private members injected,
    // and 'gInject' was last @Injected in Super, so that remains the owner
    assertPoints(points, Super.class, "privateAtAndPublicG", "privateGAndPublicAt", "gInject");
    // Subclass also has the "private" methods, but they do not override
    // the superclass' methods, and it now owns the inject2 methods.
    assertPoints(points, Sub.class, "privateAtAndPublicG", "privateGAndPublicAt",
        "atFirstThenG", "gFirstThenAt");
    
    points = InjectionPoint.forInstanceMethodsAndFields(SubSub.class);
    assertEquals(points.toString(), 6, points.size());
    // Superclass still has all the injection points it did before..
    assertPoints(points, Super.class, "privateAtAndPublicG", "privateGAndPublicAt", "gInject");
    // Subclass is missing the privateGAndPublicAt because it first became public with
    // javax.inject.Inject and was overrode without an annotation, which means it
    // disappears.  (It was guice @Inject in Super, but it was private there, so it doesn't
    // effect the annotations of the subclasses.)
    assertPoints(points, Sub.class, "privateAtAndPublicG", "atFirstThenG", "gFirstThenAt");    
  }
  
  private void assertPoints(Iterable<InjectionPoint> points, Class clazz, String... methodNames) {
    Set<String> methods = new HashSet<String>();
    for(InjectionPoint point : points) {
      if(point.getDeclaringType().getRawType() == clazz) {
        methods.add(point.getMember().getName());
      }
    }
    assertEquals(points.toString(), ImmutableSet.copyOf(methodNames), methods);
  }
  
  static class Super {
    @javax.inject.Inject public void atInject() {}
    @com.google.inject.Inject public void gInject() {}

    @javax.inject.Inject private void privateAtAndPublicG() {}
    @com.google.inject.Inject private void privateGAndPublicAt() {}

    @javax.inject.Inject public void atFirstThenG() {}
    @com.google.inject.Inject public void gFirstThenAt() {}
  }
  
  static class Sub extends Super {
    public void atInject() {}
    public void gInject() {}
    
    @com.google.inject.Inject public void privateAtAndPublicG() {}
    @javax.inject.Inject public void privateGAndPublicAt() {}
    
    @com.google.inject.Inject public void atFirstThenG() {}
    @javax.inject.Inject public void gFirstThenAt() {}
  }
  
  static class SubSub extends Sub {
    public void privateAtAndPublicG() {}
    public void privateGAndPublicAt() {}
    
    public void atFirstThenG() {}
    public void gFirstThenAt() {}
  }
}
