/**
 * Copyright (C) 2010 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.inject.internal.util.Lists;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.util.Arrays;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.logging.Logger;

import junit.framework.TestCase;

import com.google.inject.spi.Element;
import com.google.inject.spi.Elements;
import com.google.inject.util.Providers;

/**
 * A suite of tests for duplicate bindings.
 * 
 * @author sameb@google.com (Sam Berlin)
 */
public class DuplicateBindingsTest extends TestCase {
  
  private FooImpl foo = new FooImpl();
  private Provider<Foo> pFoo = Providers.<Foo>of(new FooImpl());
  private Class<? extends Provider<? extends Foo>> pclFoo = FooProvider.class;
  private Class<? extends Foo> clFoo = FooImpl.class;
  private Constructor<FooImpl> cFoo = FooImpl.cxtor();

  public void testDuplicateBindingsAreIgnored() {
    Injector injector = Guice.createInjector(
        new SimpleModule(foo, pFoo, pclFoo, clFoo, cFoo),
        new SimpleModule(foo, pFoo, pclFoo, clFoo, cFoo)
    );
    List<Key<?>> bindings = Lists.newArrayList(injector.getAllBindings().keySet());
    removeBasicBindings(bindings);
    
    // Ensure only one binding existed for each type.
    assertTrue(bindings.remove(Key.get(Foo.class, named("instance"))));
    assertTrue(bindings.remove(Key.get(Foo.class, named("pInstance"))));
    assertTrue(bindings.remove(Key.get(Foo.class, named("pKey"))));
    assertTrue(bindings.remove(Key.get(Foo.class, named("linkedKey"))));
    assertTrue(bindings.remove(Key.get(FooImpl.class)));
    assertTrue(bindings.remove(Key.get(Foo.class, named("constructor"))));
    assertTrue(bindings.remove(Key.get(FooProvider.class))); // JIT binding
    
    assertEquals(bindings.toString(), 0, bindings.size());
  }
  
  public void testElementsDeduplicate() {
    List<Element> elements = Elements.getElements(
        new SimpleModule(foo, pFoo, pclFoo, clFoo, cFoo),
        new SimpleModule(foo, pFoo, pclFoo, clFoo, cFoo)
    );
    assertEquals(12, elements.size());
    assertEquals(6, new LinkedHashSet<Element>(elements).size());
  }
  
  public void testSameScopeInstanceIgnored() {
    Guice.createInjector(
        new ScopedModule(Scopes.SINGLETON, foo, pFoo, pclFoo, clFoo, cFoo),
        new ScopedModule(Scopes.SINGLETON, foo, pFoo, pclFoo, clFoo, cFoo)
    );
    
    Guice.createInjector(
        new ScopedModule(Scopes.NO_SCOPE, foo, pFoo, pclFoo, clFoo, cFoo),
        new ScopedModule(Scopes.NO_SCOPE, foo, pFoo, pclFoo, clFoo, cFoo)
    );
  }
  
  public void testSameScopeAnnotationIgnored() {
    Guice.createInjector(
        new AnnotatedScopeModule(Singleton.class, foo, pFoo, pclFoo, clFoo, cFoo),
        new AnnotatedScopeModule(Singleton.class, foo, pFoo, pclFoo, clFoo, cFoo)
    );
  }
  
  public void testMixedAnnotationAndScopeForSingletonIgnored() {
    Guice.createInjector(
        new ScopedModule(Scopes.SINGLETON, foo, pFoo, pclFoo, clFoo, cFoo),
        new AnnotatedScopeModule(Singleton.class, foo, pFoo, pclFoo, clFoo, cFoo)
    );
  }
  
  public void testMixedScopeAndUnscopedIgnored() {
    Guice.createInjector(
        new SimpleModule(foo, pFoo, pclFoo, clFoo, cFoo),
        new ScopedModule(Scopes.NO_SCOPE, foo, pFoo, pclFoo, clFoo, cFoo)
    );
  }
  
  public void testMixedScopeFails() {
    try {
      Guice.createInjector(
          new SimpleModule(foo, pFoo, pclFoo, clFoo, cFoo),
          new ScopedModule(Scopes.SINGLETON, foo, pFoo, pclFoo, clFoo, cFoo)
      );
      fail("expected exception");
    } catch(CreationException ce) {
      assertContains(ce.getMessage(), 
          "A binding to " + Foo.class.getName() + " annotated with " + named("pInstance") + " was already configured at " + SimpleModule.class.getName(),
          "at " + ScopedModule.class.getName(), 
          "A binding to " + Foo.class.getName() + " annotated with " + named("pKey") + " was already configured at " + SimpleModule.class.getName(),
          "at " + ScopedModule.class.getName(), 
          "A binding to " + Foo.class.getName() + " annotated with " + named("linkedKey") + " was already configured at " + SimpleModule.class.getName(),
          "at " + ScopedModule.class.getName(), 
          "A binding to " + FooImpl.class.getName() + " was already configured at " + SimpleModule.class.getName(),
          "at " + ScopedModule.class.getName(), 
          "A binding to " + Foo.class.getName() + " annotated with " + named("constructor") + " was already configured at " + SimpleModule.class.getName(),
          "at " + ScopedModule.class.getName());
    }
  }
  
  @SuppressWarnings("unchecked")
  public void testMixedTargetsFails() {
    try {
      Guice.createInjector(
          new SimpleModule(foo, pFoo, pclFoo, clFoo, cFoo),
          new SimpleModule(new FooImpl(), Providers.<Foo>of(new FooImpl()), 
              (Class)BarProvider.class, (Class)Bar.class, (Constructor)Bar.cxtor())
      );
      fail("expected exception");
    } catch(CreationException ce) {
      assertContains(ce.getMessage(), 
          "A binding to " + Foo.class.getName() + " annotated with " + named("pInstance") + " was already configured at " + SimpleModule.class.getName(),
          "at " + SimpleModule.class.getName(), 
          "A binding to " + Foo.class.getName() + " annotated with " + named("pKey") + " was already configured at " + SimpleModule.class.getName(),
          "at " + SimpleModule.class.getName(), 
          "A binding to " + Foo.class.getName() + " annotated with " + named("linkedKey") + " was already configured at " + SimpleModule.class.getName(),
          "at " + SimpleModule.class.getName(),
          "A binding to " + Foo.class.getName() + " annotated with " + named("constructor") + " was already configured at " + SimpleModule.class.getName(),
          "at " + SimpleModule.class.getName());
    }
  }
  
  public void testExceptionInEqualsThrowsCreationException() {
    try {
      Guice.createInjector(new ThrowingModule(), new ThrowingModule());
      fail("expected exception");
    } catch(CreationException ce) {
      assertContains(ce.getMessage(),
          "A binding to " + Foo.class.getName() + " was already configured at " + ThrowingModule.class.getName(),
          "and an error was thrown while checking duplicate bindings.  Error: java.lang.RuntimeException: Boo!",
          "at " + ThrowingModule.class.getName());
    }
  }
  
  public void testChildInjectorDuplicateParentFail() {
    Injector injector = Guice.createInjector(
        new SimpleModule(foo, pFoo, pclFoo, clFoo, cFoo)
    );
    
    try {
      injector.createChildInjector(
          new SimpleModule(foo, pFoo, pclFoo, clFoo, cFoo)
      );
      fail("expected exception");
    } catch(CreationException ce) {
      assertContains(ce.getMessage(), 
          "A binding to " + Foo.class.getName() + " annotated with " + named("pInstance") + " was already configured at " + SimpleModule.class.getName(),
          "at " + SimpleModule.class.getName(), 
          "A binding to " + Foo.class.getName() + " annotated with " + named("pKey") + " was already configured at " + SimpleModule.class.getName(),
          "at " + SimpleModule.class.getName(), 
          "A binding to " + Foo.class.getName() + " annotated with " + named("linkedKey") + " was already configured at " + SimpleModule.class.getName(),
          "at " + SimpleModule.class.getName(),
          "A binding to " + Foo.class.getName() + " annotated with " + named("constructor") + " was already configured at " + SimpleModule.class.getName(),
          "at " + SimpleModule.class.getName());
    } 
  }
  
  public void testDuplicatesSolelyInChildIgnored() {
    Injector injector = Guice.createInjector();
    injector.createChildInjector(
        new SimpleModule(foo, pFoo, pclFoo, clFoo, cFoo),
        new SimpleModule(foo, pFoo, pclFoo, clFoo, cFoo)
    );
  }
  
  public void testDifferentBindingTypesFail() {
    List<Element> elements = Elements.getElements(
        new FailedModule(foo, pFoo, pclFoo, clFoo, cFoo)
    );
    
    // Make sure every combination of the elements with another element fails.
    // This ensures that duplication checks the kind of binding also.
    for(Element e1 : elements) {
      for(Element e2: elements) {
        // if they're the same, this shouldn't fail.
        try {
          Guice.createInjector(Elements.getModule(Arrays.asList(e1, e2)));
          if(e1 != e2) {
            fail("must fail!");
          }
        } catch(CreationException expected) {
          if(e1 != e2) {
            assertContains(expected.getMessage(),
                "A binding to " + Foo.class.getName() + " was already configured at " + FailedModule.class.getName(),
                "at " + FailedModule.class.getName());
          } else {
            throw expected;
          }
        }
      }
    }
  }
  
  public void testJitBindingsAreCheckedAfterConversions() {
    Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
       bind(A.class);
       bind(A.class).to(RealA.class);
      }
    });
  }
  
  private static class RealA extends A {}
  @ImplementedBy(RealA.class) private static class A {}
  
  private void removeBasicBindings(Collection<Key<?>> bindings) {
    bindings.remove(Key.get(Injector.class));
    bindings.remove(Key.get(Logger.class));
    bindings.remove(Key.get(Stage.class));
  }
  
  private static class ThrowingModule extends AbstractModule {
    @Override
    protected void configure() {
      bind(Foo.class).toInstance(new Foo() {
        @Override
        public boolean equals(Object obj) {
          throw new RuntimeException("Boo!");
        }
      });
    }
  }
  
  private static abstract class FooModule extends AbstractModule {
    protected final FooImpl foo;
    protected final Provider<Foo> pFoo;
    protected final Class<? extends Provider<? extends Foo>> pclFoo;
    protected final Class<? extends Foo> clFoo;
    protected final Constructor<FooImpl> cFoo;
    
    FooModule(FooImpl foo, Provider<Foo> pFoo, Class<? extends Provider<? extends Foo>> pclFoo,
        Class<? extends Foo> clFoo, Constructor<FooImpl> cFoo) {
      this.foo = foo;
      this.pFoo = pFoo;
      this.pclFoo = pclFoo;
      this.clFoo = clFoo;
      this.cFoo = cFoo;
    }    
  }
  
  private static class FailedModule extends FooModule {
    FailedModule(FooImpl foo, Provider<Foo> pFoo, Class<? extends Provider<? extends Foo>> pclFoo,
        Class<? extends Foo> clFoo, Constructor<FooImpl> cFoo) {
      super(foo, pFoo, pclFoo, clFoo, cFoo);
    }
    
    protected void configure() {
      // InstanceBinding
      bind(Foo.class).toInstance(foo);
      
      // ProviderInstanceBinding
      bind(Foo.class).toProvider(pFoo);
      
      // ProviderKeyBinding
      bind(Foo.class).toProvider(pclFoo);
      
      // LinkedKeyBinding
      bind(Foo.class).to(clFoo);
      
      // ConstructorBinding
      bind(Foo.class).toConstructor(cFoo);
    }
  }  
  
  private static class SimpleModule extends FooModule {
    SimpleModule(FooImpl foo, Provider<Foo> pFoo, Class<? extends Provider<? extends Foo>> pclFoo,
        Class<? extends Foo> clFoo, Constructor<FooImpl> cFoo) {
      super(foo, pFoo, pclFoo, clFoo, cFoo);
    }
    
    protected void configure() {
      // InstanceBinding
      bind(Foo.class).annotatedWith(named("instance")).toInstance(foo);
      
      // ProviderInstanceBinding
      bind(Foo.class).annotatedWith(named("pInstance")).toProvider(pFoo);
      
      // ProviderKeyBinding
      bind(Foo.class).annotatedWith(named("pKey")).toProvider(pclFoo);
      
      // LinkedKeyBinding
      bind(Foo.class).annotatedWith(named("linkedKey")).to(clFoo);
      
      // UntargettedBinding / ConstructorBinding
      bind(FooImpl.class);
      
      // ConstructorBinding
      bind(Foo.class).annotatedWith(named("constructor")).toConstructor(cFoo);
    }
  }
  
  private static class ScopedModule extends FooModule {
    private final Scope scope;

    ScopedModule(Scope scope, FooImpl foo, Provider<Foo> pFoo,
        Class<? extends Provider<? extends Foo>> pclFoo, Class<? extends Foo> clFoo,
        Constructor<FooImpl> cFoo) {
      super(foo, pFoo, pclFoo, clFoo, cFoo);
      this.scope = scope;
    }
    
    protected void configure() {
      // ProviderInstanceBinding
      bind(Foo.class).annotatedWith(named("pInstance")).toProvider(pFoo).in(scope);
      
      // ProviderKeyBinding
      bind(Foo.class).annotatedWith(named("pKey")).toProvider(pclFoo).in(scope);
      
      // LinkedKeyBinding
      bind(Foo.class).annotatedWith(named("linkedKey")).to(clFoo).in(scope);
      
      // UntargettedBinding / ConstructorBinding
      bind(FooImpl.class).in(scope);
      
      // ConstructorBinding
      bind(Foo.class).annotatedWith(named("constructor")).toConstructor(cFoo).in(scope);
    }
  }
  
  private static class AnnotatedScopeModule extends FooModule {
    private final Class<? extends Annotation> scope;

    AnnotatedScopeModule(Class<? extends Annotation> scope, FooImpl foo, Provider<Foo> pFoo,
        Class<? extends Provider<? extends Foo>> pclFoo, Class<? extends Foo> clFoo,
        Constructor<FooImpl> cFoo) {
      super(foo, pFoo, pclFoo, clFoo, cFoo);
      this.scope = scope;
    }
    
    
    protected void configure() {
      // ProviderInstanceBinding
      bind(Foo.class).annotatedWith(named("pInstance")).toProvider(pFoo).in(scope);
      
      // ProviderKeyBinding
      bind(Foo.class).annotatedWith(named("pKey")).toProvider(pclFoo).in(scope);
      
      // LinkedKeyBinding
      bind(Foo.class).annotatedWith(named("linkedKey")).to(clFoo).in(scope);
      
      // UntargettedBinding / ConstructorBinding
      bind(FooImpl.class).in(scope);
      
      // ConstructorBinding
      bind(Foo.class).annotatedWith(named("constructor")).toConstructor(cFoo).in(scope);
    }
  }  
  
  private static interface Foo {}
  private static class FooImpl implements Foo {
    @Inject public FooImpl() {}
    
    private static Constructor<FooImpl> cxtor() {
      try {
        return FooImpl.class.getConstructor();
      } catch (SecurityException e) {
        throw new RuntimeException(e);
      } catch (NoSuchMethodException e) {
        throw new RuntimeException(e);
      }
    }
  }  
  private static class FooProvider implements Provider<Foo> {
    public Foo get() {
      return new FooImpl();
    }
  }
  
  private static class Bar implements Foo {
    @Inject public Bar() {}
    
    private static Constructor<Bar> cxtor() {
      try {
        return Bar.class.getConstructor();
      } catch (SecurityException e) {
        throw new RuntimeException(e);
      } catch (NoSuchMethodException e) {
        throw new RuntimeException(e);
      }
    }
  }  
  private static class BarProvider implements Provider<Foo> {
    public Foo get() {
      return new Bar();
    }
  }  
  
}
