/**
 * 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.assertContains;
import static com.google.inject.Asserts.assertNotSerializable;
import java.io.IOException;
import java.lang.annotation.Retention;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicReference;
import junit.framework.TestCase;

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

  @Retention(RUNTIME)
  @BindingAnnotation @interface Other {}

  @Retention(RUNTIME)
  @BindingAnnotation @interface S {}

  @Retention(RUNTIME)
  @BindingAnnotation @interface I {}

  public void testToStringDoesNotInfinitelyRecurse() {
    Injector injector = Guice.createInjector(Stage.TOOL);
    injector.toString();
    injector.getBinding(Injector.class).toString();
  }

  public void testProviderMethods() throws CreationException {
    final SampleSingleton singleton = new SampleSingleton();
    final SampleSingleton other = new SampleSingleton();

    Injector injector = Guice.createInjector(new AbstractModule() {
      protected void configure() {
        bind(SampleSingleton.class).toInstance(singleton);
        bind(SampleSingleton.class)
            .annotatedWith(Other.class)
            .toInstance(other);
      }
    });

    assertSame(singleton,
        injector.getInstance(Key.get(SampleSingleton.class)));
    assertSame(singleton, injector.getInstance(SampleSingleton.class));

    assertSame(other,
        injector.getInstance(Key.get(SampleSingleton.class, Other.class)));
  }

  static class SampleSingleton {}

  public void testInjection() throws CreationException {
    Injector injector = createFooInjector();
    Foo foo = injector.getInstance(Foo.class);

    assertEquals("test", foo.s);
    assertEquals("test", foo.bar.getTee().getS());
    assertSame(foo.bar, foo.copy);
    assertEquals(5, foo.i);
    assertEquals(5, foo.bar.getI());

    // Test circular dependency.
    assertSame(foo.bar, foo.bar.getTee().getBar());
  }

  private Injector createFooInjector() throws CreationException {
    return Guice.createInjector(new AbstractModule() {
      protected void configure() {
        bind(Bar.class).to(BarImpl.class);
        bind(Tee.class).to(TeeImpl.class);
        bindConstant().annotatedWith(S.class).to("test");
        bindConstant().annotatedWith(I.class).to(5);
      }
    });
  }

  public void testGetInstance() throws CreationException {
    Injector injector = createFooInjector();

    Bar bar = injector.getInstance(Key.get(Bar.class));
    assertEquals("test", bar.getTee().getS());
    assertEquals(5, bar.getI());
  }

  public void testIntAndIntegerAreInterchangeable()
      throws CreationException {
    Injector injector = Guice.createInjector(new AbstractModule() {
      protected void configure() {
        bindConstant().annotatedWith(I.class).to(5);
      }
    });

    IntegerWrapper iw = injector.getInstance(IntegerWrapper.class);
    assertEquals(5, (int) iw.i);
  }

  public void testInjectorApiIsNotSerializable() throws IOException {
    Injector injector = Guice.createInjector();
    assertNotSerializable(injector);
    assertNotSerializable(injector.getProvider(String.class));
    assertNotSerializable(injector.getBinding(String.class));
    for (Binding<?> binding : injector.getBindings().values()) {
      assertNotSerializable(binding);
    }
  }

  static class IntegerWrapper {
    @Inject @I Integer i;
  }

  static class Foo {

    @Inject Bar bar;
    @Inject Bar copy;

    @Inject @S String s;

    int i;

    @Inject
    void setI(@I int i) {
      this.i = i;
    }
  }

  interface Bar {

    Tee getTee();
    int getI();
  }

  @Singleton
  static class BarImpl implements Bar {

    @Inject @I int i;

    Tee tee;

    @Inject
    void initialize(Tee tee) {
      this.tee = tee;
    }

    public Tee getTee() {
      return tee;
    }

    public int getI() {
      return i;
    }
  }

  interface Tee {

    String getS();
    Bar getBar();
  }

  static class TeeImpl implements Tee {

    final String s;
    @Inject Bar bar;

    @Inject
    TeeImpl(@S String s) {
      this.s = s;
    }

    public String getS() {
      return s;
    }

    public Bar getBar() {
      return bar;
    }
  }

  public void testInjectStatics() throws CreationException {
    Guice.createInjector(new AbstractModule() {
      protected void configure() {
        bindConstant().annotatedWith(S.class).to("test");
        bindConstant().annotatedWith(I.class).to(5);
        requestStaticInjection(Static.class);
      }
    });

    assertEquals("test", Static.s);
    assertEquals(5, Static.i);
  }

  static class Static {

    @Inject @I static int i;

    static String s;

    @Inject static void setS(@S String s) {
      Static.s = s;
    }
  }

  public void testPrivateInjection() throws CreationException {
    Injector injector = Guice.createInjector(new AbstractModule() {
      protected void configure() {
        bind(String.class).toInstance("foo");
        bind(int.class).toInstance(5);
      }
    });

    Private p = injector.getInstance(Private.class);
    assertEquals("foo", p.fromConstructor);
    assertEquals(5, p.fromMethod);
  }

  static class Private {
    String fromConstructor;
    int fromMethod;

    @Inject
    private Private(String fromConstructor) {
      this.fromConstructor = fromConstructor;
    }

    @Inject
    private void setInt(int i) {
      this.fromMethod = i;
    }
  }

  public void testProtectedInjection() throws CreationException {
    Injector injector = Guice.createInjector(new AbstractModule() {
      protected void configure() {
        bind(String.class).toInstance("foo");
        bind(int.class).toInstance(5);
      }
    });

    Protected p = injector.getInstance(Protected.class);
    assertEquals("foo", p.fromConstructor);
    assertEquals(5, p.fromMethod);
  }

  static class Protected {
    String fromConstructor;
    int fromMethod;

    @Inject
    protected Protected(String fromConstructor) {
      this.fromConstructor = fromConstructor;
    }

    @Inject
    protected void setInt(int i) {
      this.fromMethod = i;
    }
  }

  public void testInstanceInjectionHappensAfterFactoriesAreSetUp() {
    Guice.createInjector(new AbstractModule() {
      protected void configure() {
        bind(Object.class).toInstance(new Object() {
          @Inject Runnable r;
        });

        bind(Runnable.class).to(MyRunnable.class);
      }
    });
  }

  public void testToolStageInjectorRestrictions() {
    Injector injector = Guice.createInjector(Stage.TOOL);
    try {
      injector.injectMembers(new Object());
      fail("Non-SPI Injector methods must throw an exception in the TOOL stage.");
    } catch (UnsupportedOperationException expected) {
    }

    try {
      injector.getInstance(Injector.class);
      fail("Non-SPI Injector methods must throw an exception in the TOOL stage.");
    } catch (UnsupportedOperationException expected) {
    }

    try {
      injector.getInstance(Key.get(Injector.class));
      fail("Non-SPI Injector methods must throw an exception in the TOOL stage.");
    } catch (UnsupportedOperationException expected) {
    }

    try {
      injector.getProvider(Injector.class);
      fail("Non-SPI Injector methods must throw an exception in the TOOL stage.");
    } catch (UnsupportedOperationException expected) {
    }

    try {
      injector.getProvider(Key.get(Injector.class));
      fail("Non-SPI Injector methods must throw an exception in the TOOL stage.");
    } catch (UnsupportedOperationException expected) {
    }
  }

  public void testSubtypeNotProvided() {
    try {
      Guice.createInjector().getInstance(Money.class);
      fail();
    } catch (ProvisionException expected) {
      assertContains(expected.getMessage(),
          Tree.class.getName() + " doesn't provide instances of " + Money.class.getName(),
          "while locating ", Tree.class.getName(),
          "while locating ", Money.class.getName());
    }
  }

  public void testNotASubtype() {
    try {
      Guice.createInjector().getInstance(PineTree.class);
      fail();
    } catch (ConfigurationException expected) {
      assertContains(expected.getMessage(),
          Tree.class.getName() + " doesn't extend " + PineTree.class.getName(),
          "while locating ", PineTree.class.getName());
    }
  }

  public void testRecursiveImplementationType() {
    try {
      Guice.createInjector().getInstance(SeaHorse.class);
      fail();
    } catch (ConfigurationException expected) {
      assertContains(expected.getMessage(),
          "@ImplementedBy points to the same class it annotates.",
          "while locating ", SeaHorse.class.getName());
    }
  }

  public void testRecursiveProviderType() {
    try {
      Guice.createInjector().getInstance(Chicken.class);
      fail();
    } catch (ConfigurationException expected) {
      assertContains(expected.getMessage(),
          "@ProvidedBy points to the same class it annotates",
          "while locating ", Chicken.class.getName());
    }
  }

  static class MyRunnable implements Runnable {
   public void run() {}
  }

  @ProvidedBy(Tree.class)
  static class Money {}

  static class Tree implements Provider<Object> {
    public Object get() {
      return "Money doesn't grow on trees";
    }
  }

  @ImplementedBy(Tree.class)
  static class PineTree extends Tree {}

  @ImplementedBy(SeaHorse.class)
  static class SeaHorse {}

  @ProvidedBy(Chicken.class)
  static class Chicken implements Provider<Chicken> {
    public Chicken get() {
      return this;
    }
  }

  public void testJitBindingFromAnotherThreadDuringInjection() {
    final ExecutorService executorService = Executors.newSingleThreadExecutor();
    final AtomicReference<JustInTime> got = new AtomicReference<JustInTime>();

    Guice.createInjector(new AbstractModule() {
      protected void configure() {
        requestInjection(new Object() {
          @Inject void initialize(final Injector injector)
              throws ExecutionException, InterruptedException {
            Future<JustInTime> future = executorService.submit(new Callable<JustInTime>() {
              public JustInTime call() throws Exception {
                return injector.getInstance(JustInTime.class);
              }
            });
            got.set(future.get());
          }
        });
      }
    });

    assertNotNull(got.get());
  }

  static class JustInTime {}
}
