/*
 * Copyright (C) 2007 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.assertContains;
import static com.google.inject.name.Names.named;

import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import com.google.common.util.concurrent.Runnables;
import com.google.inject.matcher.Matchers;
import com.google.inject.spi.InjectionPoint;
import com.google.inject.spi.TypeEncounter;
import com.google.inject.spi.TypeListener;

import junit.framework.TestCase;

/*if[AOP]*/
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
/*end[AOP]*/

import java.lang.reflect.Constructor;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Logger;

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

  static class Dependent {
    @Inject A a;
    @Inject Dependent(A a, B b) {}
    @Inject void injectBob(Bob bob) {}
  }

  public void testExplicitCyclicDependency() {
    Guice.createInjector(new AbstractModule() {
      protected void configure() {
        bind(A.class);
        bind(B.class);
      }
    }).getInstance(A.class);
  }

  static class A { @Inject B b; }
  static class B { @Inject A a; }

  static class Bob {}

  static class MyModule extends AbstractModule {

    protected void configure() {
      // Linked.
      bind(Object.class).to(Runnable.class).in(Scopes.SINGLETON);

      // Instance.
      bind(Runnable.class).toInstance(Runnables.doNothing());

      // Provider instance.
      bind(Foo.class).toProvider(new Provider<Foo>() {
        public Foo get() {
          return new Foo();
        }
      }).in(Scopes.SINGLETON);

      // Provider.
      bind(Foo.class)
          .annotatedWith(named("provider"))
          .toProvider(FooProvider.class);

      // Class.
      bind(Bar.class).in(Scopes.SINGLETON);

      // Constant.
      bindConstant().annotatedWith(named("name")).to("Bob");
    }
  }

  static class Foo {}

  public static class FooProvider implements Provider<Foo> {
    public Foo get() {
      throw new UnsupportedOperationException();
    }
  }

  public static class Bar {}

  public void testBindToUnboundLinkedBinding() {
    try {
      Guice.createInjector(new AbstractModule() {
        protected void configure() {
          bind(Collection.class).to(List.class);
        }
      });
      fail();
    } catch (CreationException expected) {
      assertContains(expected.getMessage(), "No implementation for java.util.List was bound.");
    }
  }

  /**
   * This test ensures that the asEagerSingleton() scoping applies to the key,
   * not to what the key is linked to.
   */
  public void testScopeIsAppliedToKeyNotTarget() {
    Injector injector = Guice.createInjector(new AbstractModule() {
      protected void configure() {
        bind(Integer.class).toProvider(Counter.class).asEagerSingleton();
        bind(Number.class).toProvider(Counter.class).asEagerSingleton();
      }
    });

    assertNotSame(injector.getInstance(Integer.class), injector.getInstance(Number.class));
  }

  static class Counter implements Provider<Integer> {
    static AtomicInteger next = new AtomicInteger(1);
    public Integer get() {
      return next.getAndIncrement();
    }
  }

  public void testAnnotatedNoArgConstructor() {
    assertBindingSucceeds(PublicNoArgAnnotated.class);
    assertBindingSucceeds(ProtectedNoArgAnnotated.class);
    assertBindingSucceeds(PackagePrivateNoArgAnnotated.class);
    assertBindingSucceeds(PrivateNoArgAnnotated.class);
  }

  static class PublicNoArgAnnotated {
    @Inject public PublicNoArgAnnotated() { }
  }

  static class ProtectedNoArgAnnotated {
    @Inject protected ProtectedNoArgAnnotated() { }
  }

  static class PackagePrivateNoArgAnnotated {
    @Inject PackagePrivateNoArgAnnotated() { }
  }

  static class PrivateNoArgAnnotated {
    @Inject private PrivateNoArgAnnotated() { }
  }

  public void testUnannotatedNoArgConstructor() throws Exception{
    assertBindingSucceeds(PublicNoArg.class);
    assertBindingSucceeds(ProtectedNoArg.class);
    assertBindingSucceeds(PackagePrivateNoArg.class);
    assertBindingSucceeds(PrivateNoArgInPrivateClass.class);
    assertBindingFails(PrivateNoArg.class);
  }

  static class PublicNoArg {
    public PublicNoArg() { }
  }

  static class ProtectedNoArg {
    protected ProtectedNoArg() { }
  }

  static class PackagePrivateNoArg {
    PackagePrivateNoArg() { }
  }

  private static class PrivateNoArgInPrivateClass {
    PrivateNoArgInPrivateClass() { }
  }

  static class PrivateNoArg {
    private PrivateNoArg() { }
  }

  private void assertBindingSucceeds(final Class<?> clazz) {
    assertNotNull(Guice.createInjector().getInstance(clazz));
  }

  private void assertBindingFails(final Class<?> clazz) throws NoSuchMethodException {
    try {
      Guice.createInjector().getInstance(clazz);
      fail();
    } catch (ConfigurationException expected) {
      assertContains(expected.getMessage(),
          "Could not find a suitable constructor in " + PrivateNoArg.class.getName(),
          "at " + PrivateNoArg.class.getName() + ".class(BindingTest.java:");
    }
  }

  public void testTooManyConstructors() {
    try {
      Guice.createInjector().getInstance(TooManyConstructors.class);
      fail();
    } catch (ConfigurationException expected) {
      assertContains(expected.getMessage(),
          TooManyConstructors.class.getName() + " has more than one constructor annotated with " 
              + "@Inject. Classes must have either one (and only one) constructor",
          "at " + TooManyConstructors.class.getName() + ".class(BindingTest.java:");
    }
  }

  static class TooManyConstructors {
    @Inject TooManyConstructors(Injector i) {}
    @Inject TooManyConstructors() {}
  }

  public void testToConstructorBinding() throws NoSuchMethodException {
    final Constructor<D> constructor = D.class.getConstructor(Stage.class);

    Injector injector = Guice.createInjector(new AbstractModule() {
      protected void configure() {
        bind(Object.class).toConstructor(constructor);
      }
    });

    D d = (D) injector.getInstance(Object.class);
    assertEquals(Stage.DEVELOPMENT, d.stage);
  }

  public void testToConstructorBindingsOnParameterizedTypes() throws NoSuchMethodException {
    final Constructor<C> constructor = C.class.getConstructor(Stage.class, Object.class);
    final Key<Object> s = new Key<Object>(named("s")) {};
    final Key<Object> i = new Key<Object>(named("i")) {};

    Injector injector = Guice.createInjector(new AbstractModule() {
      protected void configure() {
        bind(s).toConstructor(constructor, new TypeLiteral<C<Stage>>() {});
        bind(i).toConstructor(constructor, new TypeLiteral<C<Injector>>() {});
      }
    });

    C<Stage> one = (C<Stage>) injector.getInstance(s);
    assertEquals(Stage.DEVELOPMENT, one.stage);
    assertEquals(Stage.DEVELOPMENT, one.t);
    assertEquals(Stage.DEVELOPMENT, one.anotherT);

    C<Injector> two = (C<Injector>) injector.getInstance(i);
    assertEquals(Stage.DEVELOPMENT, two.stage);
    assertEquals(injector, two.t);
    assertEquals(injector, two.anotherT);
  }

  public void testToConstructorBindingsFailsOnRawTypes() throws NoSuchMethodException {
    final Constructor constructor = C.class.getConstructor(Stage.class, Object.class);

    try {
      Guice.createInjector(new AbstractModule() {
        protected void configure() {
          bind(Object.class).toConstructor(constructor);
        }
      });
      fail();
    } catch (CreationException expected) {
      assertContains(expected.getMessage(),
          "1) T cannot be used as a key; It is not fully specified.",
          "at " + C.class.getName() + ".<init>(BindingTest.java:",
          "2) T cannot be used as a key; It is not fully specified.",
          "at " + C.class.getName() + ".anotherT(BindingTest.java:");
    }
  }

/*if[AOP]*/
  public void testToConstructorAndMethodInterceptors() throws NoSuchMethodException {
    final Constructor<D> constructor = D.class.getConstructor(Stage.class);
    final AtomicInteger count = new AtomicInteger();
    final MethodInterceptor countingInterceptor = new MethodInterceptor() {
      public Object invoke(MethodInvocation methodInvocation) throws Throwable {
        count.incrementAndGet();
        return methodInvocation.proceed();
      }
    };

    Injector injector = Guice.createInjector(new AbstractModule() {
      protected void configure() {
        bind(Object.class).toConstructor(constructor);
        bindInterceptor(Matchers.any(), Matchers.any(), countingInterceptor);
      }
    });

    D d = (D) injector.getInstance(Object.class);
    d.hashCode();
    d.hashCode();
    assertEquals(2, count.get());
  }
/*end[AOP]*/

  public void testInaccessibleConstructor() throws NoSuchMethodException {
    final Constructor<E> constructor = E.class.getDeclaredConstructor(Stage.class);

    Injector injector = Guice.createInjector(new AbstractModule() {
      protected void configure() {
        bind(E.class).toConstructor(constructor);
      }
    });

    E e = injector.getInstance(E.class);
    assertEquals(Stage.DEVELOPMENT, e.stage);
  }

  public void testToConstructorAndScopes() throws NoSuchMethodException {
    final Constructor<F> constructor = F.class.getConstructor(Stage.class);

    final Key<Object> d = Key.get(Object.class, named("D")); // default scoping
    final Key<Object> s = Key.get(Object.class, named("S")); // singleton
    final Key<Object> n = Key.get(Object.class, named("N")); // "N" instances
    final Key<Object> r = Key.get(Object.class, named("R")); // a regular binding

    Injector injector = Guice.createInjector(new AbstractModule() {
      protected void configure() {
        bind(d).toConstructor(constructor);
        bind(s).toConstructor(constructor).in(Singleton.class);
        bind(n).toConstructor(constructor).in(Scopes.NO_SCOPE);
        bind(r).to(F.class);
      }
    });

    assertDistinct(injector, 1, d, d, d, d);
    assertDistinct(injector, 1, s, s, s, s);
    assertDistinct(injector, 4, n, n, n, n);
    assertDistinct(injector, 1, r, r, r, r);
    assertDistinct(injector, 4, d, d, r, r, s, s, n);
  }

  public void assertDistinct(Injector injector, int expectedCount, Key<?>... keys) {
    ImmutableSet.Builder<Object> builder = ImmutableSet.builder();
    for (Key<?> k : keys) {
      builder.add(injector.getInstance(k));
    }
    assertEquals(expectedCount, builder.build().size());
  }

  public void testToConstructorSpiData() throws NoSuchMethodException {
    final Set<TypeLiteral<?>> heardTypes = Sets.newHashSet();

    final Constructor<D> constructor = D.class.getConstructor(Stage.class);
    final TypeListener listener = new TypeListener() {
      public <I> void hear(TypeLiteral<I> type, TypeEncounter<I> encounter) {
        if (!heardTypes.add(type)) {
          fail("Heard " + type + " multiple times!");
        }
      }
    };

    Guice.createInjector(new AbstractModule() {
      protected void configure() {
        bind(Object.class).toConstructor(constructor);
        bind(D.class).toConstructor(constructor);
        bindListener(Matchers.any(), listener);
      }
    });
    
    assertEquals(ImmutableSet.of(TypeLiteral.get(D.class)), heardTypes);
  }

  public void testInterfaceToImplementationConstructor() throws NoSuchMethodException {
    final Constructor<CFoo> constructor = CFoo.class.getDeclaredConstructor();

    Injector injector = Guice.createInjector(new AbstractModule() {
      protected void configure() {
        bind(IFoo.class).toConstructor(constructor);
      }
    });

    injector.getInstance(IFoo.class);
  }

  public static interface IFoo {}
  public static class CFoo implements IFoo {}

  public void testGetAllBindings() {
    Injector injector = Guice.createInjector(new AbstractModule() {
      protected void configure() {
        bind(D.class).toInstance(new D(Stage.PRODUCTION));
        bind(Object.class).to(D.class);
        getProvider(new Key<C<Stage>>() {});
      }
    });

    Map<Key<?>,Binding<?>> bindings = injector.getAllBindings();
    assertEquals(ImmutableSet.of(Key.get(Injector.class), Key.get(Stage.class), Key.get(D.class),
        Key.get(Logger.class), Key.get(Object.class), new Key<C<Stage>>() {}),
        bindings.keySet());

    // add a JIT binding
    injector.getInstance(F.class);

    Map<Key<?>,Binding<?>> bindings2 = injector.getAllBindings();
    assertEquals(ImmutableSet.of(Key.get(Injector.class), Key.get(Stage.class), Key.get(D.class),
        Key.get(Logger.class), Key.get(Object.class), new Key<C<Stage>>() {}, Key.get(F.class)),
        bindings2.keySet());

    // the original map shouldn't have changed
    assertEquals(ImmutableSet.of(Key.get(Injector.class), Key.get(Stage.class), Key.get(D.class),
        Key.get(Logger.class), Key.get(Object.class), new Key<C<Stage>>() {}),
        bindings.keySet());

    // check the bindings' values
    assertEquals(injector, bindings.get(Key.get(Injector.class)).getProvider().get());
  }

  public void testGetAllServletBindings() throws Exception {
    Injector injector = Guice.createInjector(new AbstractModule() {
      protected void configure() {
        bind(F.class); // an explicit binding that uses a JIT binding for a constructor
      }
    });
    injector.getAllBindings();
  }

  public static class C<T> {
    private Stage stage;
    private T t;
    @Inject T anotherT;

    public C(Stage stage, T t) {
      this.stage = stage;
      this.t = t;
    }

    @Inject C() {}
  }

  public static class D {
    Stage stage;
    public D(Stage stage) {
      this.stage = stage;
    }
  }

  private static class E {
    Stage stage;
    private E(Stage stage) {
      this.stage = stage;
    }
  }

  @Singleton
  public static class F {
    Stage stage;
    @Inject public F(Stage stage) {
      this.stage = stage;
    }
  }
  
  public void testTurkeyBaconProblemUsingToConstuctor() {
    Injector injector = Guice.createInjector(new AbstractModule() {
      @SuppressWarnings("unchecked")
      @Override
      public void configure() {
        bind(Bacon.class).to(UncookedBacon.class);
        bind(Bacon.class).annotatedWith(named("Turkey")).to(TurkeyBacon.class);
        bind(Bacon.class).annotatedWith(named("Cooked")).toConstructor(
            (Constructor)InjectionPoint.forConstructorOf(Bacon.class).getMember());
      }
    });
    Bacon bacon = injector.getInstance(Bacon.class);
    assertEquals(Food.PORK, bacon.getMaterial());
    assertFalse(bacon.isCooked());
    
    Bacon turkeyBacon = injector.getInstance(Key.get(Bacon.class, named("Turkey")));
    assertEquals(Food.TURKEY, turkeyBacon.getMaterial());
    assertTrue(turkeyBacon.isCooked());
    
    Bacon cookedBacon = injector.getInstance(Key.get(Bacon.class, named("Cooked")));
    assertEquals(Food.PORK, cookedBacon.getMaterial());
    assertTrue(cookedBacon.isCooked());    
  }
  
  enum Food { TURKEY, PORK }
  
  private static class Bacon {
    public Food getMaterial() { return Food.PORK; }
    public boolean isCooked() { return true; }
  }

  private static class TurkeyBacon extends Bacon {
    public Food getMaterial() { return Food.TURKEY; }
  }

  private static class UncookedBacon extends Bacon {
    public boolean isCooked() { return false; }
  }
}
