/**
 * 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.asModuleChain;
import static com.google.inject.Asserts.assertContains;
import static com.google.inject.Asserts.assertNotSerializable;
import static com.google.inject.Asserts.getDeclaringSourcePart;
import static com.google.inject.Asserts.isIncludeStackTraceOff;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.inject.name.Named;
import com.google.inject.name.Names;
import com.google.inject.spi.Message;
import com.google.inject.util.Providers;

import junit.framework.TestCase;

import java.io.IOException;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.logging.Handler;
import java.util.logging.LogRecord;
import java.util.logging.Logger;

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

  private final Logger loggerToWatch = Logger.getLogger(Guice.class.getName());

  private final List<LogRecord> logRecords = Lists.newArrayList();
  private final Handler fakeHandler = new Handler() {
    @Override
    public void publish(LogRecord logRecord) {
      logRecords.add(logRecord);
    }
    @Override
    public void flush() {}
    @Override
    public void close() throws SecurityException {}
  };

  Provider<Foo> fooProvider;

  @Override protected void setUp() throws Exception {
    super.setUp();
    loggerToWatch.addHandler(fakeHandler);
  }

  @Override protected void tearDown() throws Exception {
    loggerToWatch.removeHandler(fakeHandler);
    super.tearDown();
  }

  public void testProviderFromBinder() {
    Guice.createInjector(new Module() {
      public void configure(Binder binder) {
        fooProvider = binder.getProvider(Foo.class);

        try {
          fooProvider.get();
        } catch (IllegalStateException e) { /* expected */ }
      }
    });

    assertNotNull(fooProvider.get());
  }

  static class Foo {}

  public void testMissingBindings() {
    try {
      Guice.createInjector(new AbstractModule() {
        @Override
        public void configure() {
          getProvider(Runnable.class);
          bind(Comparator.class);
          requireBinding(Key.get(new TypeLiteral<Callable<String>>() {}));
          bind(Date.class).annotatedWith(Names.named("date"));
        }
      });
    } catch (CreationException e) {
      assertEquals(4, e.getErrorMessages().size());
      String segment1 = "No implementation for " + Comparator.class.getName() + " was bound.";
      String segment2 = "No implementation for java.util.Date annotated with @"
          + Named.class.getName() + "(value=date) was bound.";
      String segment3 = "No implementation for java.lang.Runnable was bound.";
      String segment4 = " No implementation for java.util.concurrent.Callable<java.lang.String> was"
          + " bound.";
      String atSegment = "at " + getClass().getName();
      String sourceFileName = getDeclaringSourcePart(getClass());
      if (isIncludeStackTraceOff()) {
        assertContains(e.getMessage(),
            segment1, atSegment, sourceFileName,
            segment2, atSegment, sourceFileName,
            segment3, atSegment, sourceFileName,
            segment4, atSegment, sourceFileName);
      } else {
        assertContains(e.getMessage(),
            segment3, atSegment, sourceFileName,
            segment1, atSegment, sourceFileName,
            segment4, atSegment, sourceFileName,
            segment2, atSegment, sourceFileName);
      } 
    }
  }

  public void testMissingDependency() {
    try {
      Guice.createInjector(new AbstractModule() {
        @Override
        public void configure() {
          bind(NeedsRunnable.class);
        }
      });
    } catch (CreationException e) {
      assertEquals(1, e.getErrorMessages().size());
      assertContains(e.getMessage(),
          "No implementation for java.lang.Runnable was bound.",
          "for field at " + NeedsRunnable.class.getName(), ".runnable(BinderTest.java:",
          "at " + getClass().getName(), getDeclaringSourcePart(getClass()));
    }
  }

  static class NeedsRunnable {
    @Inject Runnable runnable;
  }

  public void testDanglingConstantBinding() {
    try {
      Guice.createInjector(new AbstractModule() {
        @Override public void configure() {
          bindConstant();
        }
      });
      fail();
    } catch (CreationException expected) {
      assertContains(expected.getMessage(),
          "1) Missing constant value. Please call to(...).",
          "at " + getClass().getName());
    }
  }

  public void testRecursiveBinding() {
    try {
      Guice.createInjector(new AbstractModule() {
        @Override public void configure() {
          bind(Runnable.class).to(Runnable.class);
        }
      });
      fail();
    } catch (CreationException expected) {
      assertContains(expected.getMessage(),
          "1) Binding points to itself.",
          "at " + getClass().getName(), getDeclaringSourcePart(getClass()));
    }
  }

  public void testBindingNullConstant() {
    try {
      Guice.createInjector(new AbstractModule() {
        @Override public void configure() {
          String none = null;
          bindConstant().annotatedWith(Names.named("nullOne")).to(none);
          bind(String.class).annotatedWith(Names.named("nullTwo")).toInstance(none);
        }
      });
      fail();
    } catch (CreationException expected) {
      assertContains(expected.getMessage(),
          "1) Binding to null instances is not allowed. Use toProvider(Providers.of(null))",
          "2) Binding to null instances is not allowed. Use toProvider(Providers.of(null))");
    }
  }

  public void testToStringOnBinderApi() {
    try {
      Guice.createInjector(new AbstractModule() {
        @Override public void configure() {
          assertEquals("Binder", binder().toString());
          assertEquals("Provider<java.lang.Integer>", getProvider(Integer.class).toString());
          assertEquals("Provider<java.util.List<java.lang.String>>",
              getProvider(Key.get(new TypeLiteral<List<String>>() {})).toString());

          assertEquals("BindingBuilder<java.lang.Integer>",
              bind(Integer.class).toString());
          assertEquals("BindingBuilder<java.lang.Integer>",
              bind(Integer.class).annotatedWith(Names.named("a")).toString());
          assertEquals("ConstantBindingBuilder", bindConstant().toString());
          assertEquals("ConstantBindingBuilder",
              bindConstant().annotatedWith(Names.named("b")).toString());
          assertEquals("AnnotatedElementBuilder",
              binder().newPrivateBinder().expose(Integer.class).toString());
        }
      });
      fail();
    } catch (CreationException ignored) {
    }
  }

  public void testNothingIsSerializableInBinderApi() {
    try {
      Guice.createInjector(new AbstractModule() {
        @Override public void configure() {
          try {
            assertNotSerializable(binder());
            assertNotSerializable(getProvider(Integer.class));
            assertNotSerializable(getProvider(Key.get(new TypeLiteral<List<String>>() {})));
            assertNotSerializable(bind(Integer.class));
            assertNotSerializable(bind(Integer.class).annotatedWith(Names.named("a")));
            assertNotSerializable(bindConstant());
            assertNotSerializable(bindConstant().annotatedWith(Names.named("b")));
          } catch (IOException e) {
            fail(e.getMessage());
          }
        }
      });
      fail();
    } catch (CreationException ignored) {
    }
  }

  /**
   * Although {@code String[].class} isn't equal to {@code new
   * GenericArrayTypeImpl(String.class)}, Guice should treat these two types
   * interchangeably.
   */
  public void testArrayTypeCanonicalization() {
    final String[] strings = new String[] { "A" };
    final Integer[] integers = new Integer[] { 1 };
    
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        bind(String[].class).toInstance(strings);
        bind(new TypeLiteral<Integer[]>() {}).toInstance(integers);
      }
    });

    assertSame(integers, injector.getInstance(Key.get(new TypeLiteral<Integer[]>() {})));
    assertSame(integers, injector.getInstance(new Key<Integer[]>() {}));
    assertSame(integers, injector.getInstance(Integer[].class));
    assertSame(strings, injector.getInstance(Key.get(new TypeLiteral<String[]>() {})));
    assertSame(strings, injector.getInstance(new Key<String[]>() {}));
    assertSame(strings, injector.getInstance(String[].class));

    try {
      Guice.createInjector(new AbstractModule() {
        @Override
        protected void configure() {
          bind(String[].class).toInstance(new String[] { "A" });
          bind(new TypeLiteral<String[]>() {}).toInstance(new String[] { "B" });
        }
      });
      fail();
    } catch (CreationException expected) {
      assertContains(expected.getMessage(),
          "1) A binding to java.lang.String[] was already configured at " + getClass().getName(),
          "at " + getClass().getName(), getDeclaringSourcePart(getClass()));
      assertContains(expected.getMessage(), "1 error");
    }
    
    // passes because duplicates are ignored
    injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        bind(String[].class).toInstance(strings);
        bind(new TypeLiteral<String[]>() {}).toInstance(strings);
      }
    });
    assertSame(strings, injector.getInstance(Key.get(new TypeLiteral<String[]>() {})));
    assertSame(strings, injector.getInstance(new Key<String[]>() {}));
    assertSame(strings, injector.getInstance(String[].class));
  }
  
  static class ParentModule extends AbstractModule {
    @Override protected void configure() {
      install(new FooModule());
      install(new BarModule());
    }
  }
  static class FooModule extends AbstractModule {
    @Override protected void configure() {
      install(new ConstantModule("foo"));
    }
  }
  static class BarModule extends AbstractModule {
    @Override protected void configure() {
      install(new ConstantModule("bar"));
    }
  }
  static class ConstantModule extends AbstractModule {
    private final String constant;
    ConstantModule(String constant) {
      this.constant = constant;
    }
    @Override protected void configure() {
      bind(String.class).toInstance(constant);
    }
  }
  
  /**
   * Binding something to two different things should give an error.
   */
  public void testSettingBindingTwice() {
    try {
      Guice.createInjector(new ParentModule());
      fail();
    } catch(CreationException expected) {
      assertContains(expected.getMessage(),
        "1) A binding to java.lang.String was already configured at " + ConstantModule.class.getName(),
        asModuleChain(ParentModule.class, FooModule.class, ConstantModule.class),
        "at " + ConstantModule.class.getName(), getDeclaringSourcePart(getClass()),
        asModuleChain(ParentModule.class, BarModule.class, ConstantModule.class));
      assertContains(expected.getMessage(), "1 error");
    }
  }
  
  /**
   * Binding an @ImplementedBy thing to something else should also fail.
   */
  public void testSettingAtImplementedByTwice() {
    try {
      Guice.createInjector(new AbstractModule() {
        @Override
        protected void configure() {
          bind(HasImplementedBy1.class);
          bind(HasImplementedBy1.class).toInstance(new HasImplementedBy1() {});
        }
      });
      fail();
    } catch(CreationException expected) {
      expected.printStackTrace();
      assertContains(expected.getMessage(),
        "1) A binding to " + HasImplementedBy1.class.getName()
        + " was already configured at " + getClass().getName(),
        "at " + getClass().getName(), getDeclaringSourcePart(getClass()));
      assertContains(expected.getMessage(), "1 error");
    }
  }

  /**
   * See issue 614, Problem One
   * http://code.google.com/p/google-guice/issues/detail?id=614
   */
  public void testJitDependencyDoesntBlockOtherExplicitBindings() {
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        bind(HasImplementedByThatNeedsAnotherImplementedBy.class);
        bind(HasImplementedBy1.class).toInstance(new HasImplementedBy1() {});
      }
    });
    injector.getAllBindings(); // just validate it doesn't throw.
    // Also validate that we're using the explicit (and not @ImplementedBy) implementation
    assertFalse(injector.getInstance(HasImplementedBy1.class) instanceof ImplementsHasImplementedBy1);
  }
  
  /**
   * See issue 614, Problem Two
   * http://code.google.com/p/google-guice/issues/detail?id=614
   */
  public void testJitDependencyCanUseExplicitDependencies() {
    Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        bind(HasImplementedByThatWantsExplicit.class);
        bind(JustAnInterface.class).toInstance(new JustAnInterface() {});
      }
    });
  }
  
  /**
   * Untargetted bindings should follow @ImplementedBy and @ProvidedBy
   * annotations if they exist. Otherwise the class should be constructed
   * directly.
   */
  public void testUntargettedBinding() {
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        bind(HasProvidedBy1.class);
        bind(HasImplementedBy1.class);
        bind(HasProvidedBy2.class);
        bind(HasImplementedBy2.class);
        bind(JustAClass.class);
      }
    });
    
    assertNotNull(injector.getInstance(HasProvidedBy1.class));
    assertNotNull(injector.getInstance(HasImplementedBy1.class));
    assertNotSame(HasProvidedBy2.class,
        injector.getInstance(HasProvidedBy2.class).getClass());
    assertSame(ExtendsHasImplementedBy2.class,
        injector.getInstance(HasImplementedBy2.class).getClass());
    assertSame(JustAClass.class, injector.getInstance(JustAClass.class).getClass());
  }

  public void testPartialInjectorGetInstance() {
    Injector injector = Guice.createInjector();
    try {
      injector.getInstance(MissingParameter.class);
      fail();
    } catch (ConfigurationException expected) {
      assertContains(expected.getMessage(),
          "1) Could not find a suitable constructor in " + NoInjectConstructor.class.getName(),
          "at " + MissingParameter.class.getName() + ".<init>(BinderTest.java:");
    }
  }

  public void testUserReportedError() {
    final Message message = new Message(getClass(), "Whoops!");
    try {
      Guice.createInjector(new AbstractModule() {
        @Override
        protected void configure() {
          addError(message);
        }
      });
      fail();
    } catch (CreationException expected) {
      assertSame(message, Iterables.getOnlyElement(expected.getErrorMessages()));
    }
  }

  public void testUserReportedErrorsAreAlsoLogged() {
    try {
      Guice.createInjector(new AbstractModule() {
        @Override
        protected void configure() {
          addError(new Message(ImmutableList.of(), "Whoops!", new IllegalArgumentException()));
        }
      });
      fail();
    } catch (CreationException expected) {
    }

    LogRecord logRecord = Iterables.getOnlyElement(this.logRecords);
    assertContains(logRecord.getMessage(),
        "An exception was caught and reported. Message: java.lang.IllegalArgumentException");
  }

  public void testBindingToProvider() {
    try {
      Guice.createInjector(new AbstractModule() {
        @Override
        protected void configure() {
          bind(new TypeLiteral<Provider<String>>() {}).toInstance(Providers.of("A"));
        }
      });
      fail();
    } catch (CreationException expected) {
      assertContains(expected.getMessage(),
          "1) Binding to Provider is not allowed.",
          "at " + BinderTest.class.getName(), getDeclaringSourcePart(getClass()));
    }
  }

  static class OuterCoreModule extends AbstractModule {
    @Override protected void configure() {
      install(new InnerCoreModule());
    }
  }
  static class InnerCoreModule extends AbstractModule {
    final Named red = Names.named("red");

    @Override protected void configure() {
      bind(AbstractModule.class).annotatedWith(red)
      .toProvider(Providers.<AbstractModule>of(null));
      bind(Binder.class).annotatedWith(red).toProvider(Providers.<Binder>of(null));
      bind(Binding.class).annotatedWith(red).toProvider(Providers.<Binding>of(null));
      bind(Injector.class).annotatedWith(red).toProvider(Providers.<Injector>of(null));
      bind(Key.class).annotatedWith(red).toProvider(Providers.<Key>of(null));
      bind(Module.class).annotatedWith(red).toProvider(Providers.<Module>of(null));
      bind(Provider.class).annotatedWith(red).toProvider(Providers.<Provider>of(null));
      bind(Scope.class).annotatedWith(red).toProvider(Providers.<Scope>of(null));
      bind(Stage.class).annotatedWith(red).toProvider(Providers.<Stage>of(null));
      bind(TypeLiteral.class).annotatedWith(red).toProvider(Providers.<TypeLiteral>of(null));
      bind(new TypeLiteral<Key<String>>() {}).toProvider(Providers.<Key<String>>of(null));
    }
  }
  public void testCannotBindToGuiceTypes() {
    try {
      Guice.createInjector(new OuterCoreModule());
      fail();
    } catch (CreationException expected) {
      assertContains(expected.getMessage(),
          "Binding to core guice framework type is not allowed: AbstractModule.",
          "at " + InnerCoreModule.class.getName() + getDeclaringSourcePart(getClass()),
          asModuleChain(OuterCoreModule.class, InnerCoreModule.class),
          
          "Binding to core guice framework type is not allowed: Binder.",
          "at " + InnerCoreModule.class.getName() + getDeclaringSourcePart(getClass()),
          asModuleChain(OuterCoreModule.class, InnerCoreModule.class),
          
          "Binding to core guice framework type is not allowed: Binding.",
          "at " + InnerCoreModule.class.getName() + getDeclaringSourcePart(getClass()),
          asModuleChain(OuterCoreModule.class, InnerCoreModule.class),
          
          "Binding to core guice framework type is not allowed: Injector.",
          "at " + InnerCoreModule.class.getName() + getDeclaringSourcePart(getClass()),
          asModuleChain(OuterCoreModule.class, InnerCoreModule.class),
          
          "Binding to core guice framework type is not allowed: Key.",
          "at " + InnerCoreModule.class.getName() + getDeclaringSourcePart(getClass()),
          asModuleChain(OuterCoreModule.class, InnerCoreModule.class),
          
          "Binding to core guice framework type is not allowed: Module.",
          "at " + InnerCoreModule.class.getName() + getDeclaringSourcePart(getClass()),
          asModuleChain(OuterCoreModule.class, InnerCoreModule.class),
          
          "Binding to Provider is not allowed.",
          "at " + InnerCoreModule.class.getName() + getDeclaringSourcePart(getClass()),
          asModuleChain(OuterCoreModule.class, InnerCoreModule.class),
          
          "Binding to core guice framework type is not allowed: Scope.",
          "at " + InnerCoreModule.class.getName() + getDeclaringSourcePart(getClass()),
          asModuleChain(OuterCoreModule.class, InnerCoreModule.class),
          
          "Binding to core guice framework type is not allowed: Stage.",
          "at " + InnerCoreModule.class.getName() + getDeclaringSourcePart(getClass()),
          asModuleChain(OuterCoreModule.class, InnerCoreModule.class),
          
          "Binding to core guice framework type is not allowed: TypeLiteral.",
          "at " + InnerCoreModule.class.getName() + getDeclaringSourcePart(getClass()),
          asModuleChain(OuterCoreModule.class, InnerCoreModule.class),
          
          "Binding to core guice framework type is not allowed: Key.",
          "at " + InnerCoreModule.class.getName() + getDeclaringSourcePart(getClass()),
          asModuleChain(OuterCoreModule.class, InnerCoreModule.class));
    }
  }

  static class MissingParameter {
    @Inject MissingParameter(NoInjectConstructor noInjectConstructor) {}
  }

  static class NoInjectConstructor {
    private NoInjectConstructor() {}
  }

  @ProvidedBy(HasProvidedBy1Provider.class)
  interface HasProvidedBy1 {}

  static class HasProvidedBy1Provider implements Provider<HasProvidedBy1> {
    public HasProvidedBy1 get() {
      return new HasProvidedBy1() {};
    }
  }

  @ImplementedBy(ImplementsHasImplementedBy1.class)
  interface HasImplementedBy1 {}

  static class ImplementsHasImplementedBy1 implements HasImplementedBy1 {}

  @ProvidedBy(HasProvidedBy2Provider.class)
  static class HasProvidedBy2 {}

  static class HasProvidedBy2Provider implements Provider<HasProvidedBy2> {
    public HasProvidedBy2 get() {
      return new HasProvidedBy2() {};
    }
  }

  @ImplementedBy(ExtendsHasImplementedBy2.class)
  static class HasImplementedBy2 {}

  static class ExtendsHasImplementedBy2 extends HasImplementedBy2 {}

  static class JustAClass {}
  
  @ImplementedBy(ImplementsHasImplementedByThatNeedsAnotherImplementedBy.class)
  static interface HasImplementedByThatNeedsAnotherImplementedBy {
  }
  
  static class ImplementsHasImplementedByThatNeedsAnotherImplementedBy
    implements HasImplementedByThatNeedsAnotherImplementedBy {
    @Inject 
    ImplementsHasImplementedByThatNeedsAnotherImplementedBy(
        HasImplementedBy1 h1n1) {}                             
  }
  
  @ImplementedBy(ImplementsHasImplementedByThatWantsExplicit.class)
  static interface HasImplementedByThatWantsExplicit {    
  }
  
  static class ImplementsHasImplementedByThatWantsExplicit
      implements HasImplementedByThatWantsExplicit {
    @Inject ImplementsHasImplementedByThatWantsExplicit(JustAnInterface jai) {}
  }
  
  static interface JustAnInterface {}


//  public void testBindInterfaceWithoutImplementation() {
//    Guice.createInjector(new AbstractModule() {
//      protected void configure() {
//        bind(Runnable.class);
//      }
//    }).getInstance(Runnable.class);
//  }

  enum Roshambo { ROCK, SCISSORS, PAPER }

  public void testInjectRawProvider() {
    try {
      Guice.createInjector().getInstance(Provider.class);
      fail();
    } catch (ConfigurationException expected) {
      Asserts.assertContains(expected.getMessage(),
          "1) Cannot inject a Provider that has no type parameter",
          "while locating " + Provider.class.getName());
    }
  }
}
