/*
 * 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.common.collect.ImmutableSet.of;
import static com.google.inject.Asserts.assertContains;
import static com.google.inject.JitBindingsTest.GetBindingCheck.ALLOW_BINDING;
import static com.google.inject.JitBindingsTest.GetBindingCheck.ALLOW_BINDING_PROVIDER;
import static com.google.inject.JitBindingsTest.GetBindingCheck.FAIL_ALL;

import junit.framework.TestCase;

import java.util.Set;

/**
 * Some tests for {@link Binder#requireExplicitBindings()}
 * 
 * @author sberlin@gmail.com (Sam Berlin)
 */
public class JitBindingsTest extends TestCase {
  
  private String jitFailed(Class<?> clazz) {
    return jitFailed(TypeLiteral.get(clazz));
  }
  
  private String jitFailed(TypeLiteral<?> clazz) {
    return "Explicit bindings are required and " + clazz + " is not explicitly bound.";
  }
  
  private String inChildMessage(Class<?> clazz) {
    return "Unable to create binding for "
        + clazz.getName()
        + ". It was already configured on one or more child injectors or private modules";
  }
  
  public void testLinkedBindingWorks() {
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        binder().requireExplicitBindings();
        bind(Foo.class).to(FooImpl.class);
      }
    });
    // Foo was explicitly bound
    ensureWorks(injector, Foo.class);
    // FooImpl was implicitly bound, it is an error to call getInstance or getProvider,
    // It is OK to call getBinding for introspection, but an error to get the provider
    // of the binding
    ensureFails(injector, ALLOW_BINDING, FooImpl.class);
  }
  
  public void testMoreBasicsWork() {
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        binder().requireExplicitBindings();
        bind(Foo.class).to(FooImpl.class);
        bind(Bar.class);
        bind(FooBar.class);
      }
    });
    // Foo, Bar & FooBar was explicitly bound    
    ensureWorks(injector, FooBar.class, Bar.class, Foo.class);
    // FooImpl was implicitly bound, it is an error to call getInstance or getProvider,
    // It is OK to call getBinding for introspection, but an error to get the provider
    // of the binding    
    ensureFails(injector, ALLOW_BINDING,  FooImpl.class);    
  }
  
  public void testLinkedEagerSingleton() {
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        binder().requireExplicitBindings();
        bind(Foo.class).to(FooImpl.class).asEagerSingleton();
      }
    });
    // Foo was explicitly bound
    ensureWorks(injector, Foo.class);
    // FooImpl was implicitly bound, it is an error to call getInstance or getProvider,
    // It is OK to call getBinding for introspection, but an error to get the provider
    // of the binding
    ensureFails(injector, ALLOW_BINDING, FooImpl.class);
  }
  
  public void testBasicsWithEagerSingleton() {
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        binder().requireExplicitBindings();
        bind(Foo.class).to(FooImpl.class).asEagerSingleton();
        bind(Bar.class);
        bind(FooBar.class);
      }
    });
    // Foo, Bar & FooBar was explicitly bound    
    ensureWorks(injector, FooBar.class, Bar.class, Foo.class);
    // FooImpl was implicitly bound, it is an error to call getInstance or getProvider,
    // It is OK to call getBinding for introspection, but an error to get the provider
    // of the binding    
    ensureFails(injector, ALLOW_BINDING,  FooImpl.class);    
  }  
  
  public void testLinkedToScoped() {
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        binder.requireExplicitBindings();
        bind(Foo.class).to(ScopedFooImpl.class);
      }
    });
    // Foo was explicitly bound
    ensureWorks(injector, Foo.class);
    // FooSingletonImpl was implicitly bound, it is an error to call getInstance or getProvider,
    // It is OK to call getBinding for introspection, but an error to get the provider
    // of the binding
    ensureFails(injector, ALLOW_BINDING, ScopedFooImpl.class);    
  }
  
  public void testBasicsWithScoped() {
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        binder().requireExplicitBindings();
        bind(Foo.class).to(ScopedFooImpl.class);
        bind(Bar.class);
        bind(FooBar.class);
      }
    });
    // Foo, Bar & FooBar was explicitly bound    
    ensureWorks(injector, FooBar.class, Bar.class, Foo.class);
    // FooSingletonImpl was implicitly bound, it is an error to call getInstance or getProvider,
    // It is OK to call getBinding for introspection, but an error to get the provider
    // of the binding    
    ensureFails(injector, ALLOW_BINDING,  ScopedFooImpl.class);   
  }
  
  public void testFailsIfInjectingScopedDirectlyWhenItIsntBound() {
    try {
      Guice.createInjector(new AbstractModule() {
        @Override
        protected void configure() {
          binder().requireExplicitBindings();
          bind(Foo.class).to(ScopedFooImpl.class);
          bind(WantsScopedFooImpl.class);
        }
      });
      fail();
    } catch(CreationException expected) {
      assertContains(expected.getMessage(), "1) " + jitFailed(ScopedFooImpl.class));
      assertTrue(expected.getMessage(), !expected.getMessage().contains("2) "));
    }
  }
  
  public void testLinkedProviderBindingWorks() {
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        binder().requireExplicitBindings();
        bind(Foo.class).toProvider(FooProvider.class);
      }
    });
    // Foo was explicitly bound
    ensureWorks(injector, Foo.class);
    // FooImpl was not bound at all (even implicitly), it is an error
    // to call getInstance, getProvider, or getBinding.
    ensureFails(injector, FAIL_ALL, FooImpl.class);
  }
  
  public void testJitGetFails() {
    try {
      Guice.createInjector(new AbstractModule() {
        @Override
        protected void configure() {
         binder().requireExplicitBindings(); 
        }
      }).getInstance(Bar.class);
      fail("should have failed");
    } catch(ConfigurationException expected) {
      assertContains(expected.getMessage(), "1) " + jitFailed(Bar.class));
      assertTrue(expected.getMessage(), !expected.getMessage().contains("2) "));
    }
  }
  
  public void testJitInjectionFails() {
    try {
      Guice.createInjector(new AbstractModule() {
        @Override
        protected void configure() {
          binder().requireExplicitBindings();
          bind(Foo.class).to(FooImpl.class);
          bind(FooBar.class);
        }
      });
      fail("should have failed");
    } catch (CreationException expected) {
      assertContains(expected.getMessage(), "1) " + jitFailed(Bar.class));
      assertTrue(expected.getMessage(), !expected.getMessage().contains("2) "));
    }
  }

  public void testJitProviderGetFails() {
    try {
      Guice.createInjector(new AbstractModule() {
        @Override
        protected void configure() {
          binder().requireExplicitBindings(); 
        }
      }).getProvider(Bar.class);
      fail("should have failed");
    } catch (ConfigurationException expected) {
      assertContains(expected.getMessage(), "1) " + jitFailed(Bar.class));
      assertTrue(expected.getMessage(), !expected.getMessage().contains("2) "));
    }
  }

  public void testJitProviderInjectionFails() {
    try {
      Guice.createInjector(new AbstractModule() {
        @Override
        protected void configure() {
          binder().requireExplicitBindings();
          bind(Foo.class).to(FooImpl.class);
          bind(ProviderFooBar.class);
        }
      });
      fail("should have failed");
    } catch (CreationException expected) {
      assertContains(expected.getMessage(), "1) " + jitFailed(Bar.class));
      assertTrue(expected.getMessage(), !expected.getMessage().contains("2) "));
    }
  }
  
  public void testImplementedBy() {
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        binder().requireExplicitBindings();
        bind(ImplBy.class);
      }
    });
    ensureWorks(injector, ImplBy.class);
    ensureFails(injector, ALLOW_BINDING, ImplByImpl.class);
  }
  
  public void testImplementedBySomethingThatIsAnnotated() {
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        binder().requireExplicitBindings();
        bind(ImplByScoped.class);
      }
    });
    ensureWorks(injector, ImplByScoped.class);
    ensureFails(injector, ALLOW_BINDING, ImplByScopedImpl.class);    
  }
  
  public void testProvidedBy() {
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        binder().requireExplicitBindings();
        bind(ProvBy.class);
      }
    });
    ensureWorks(injector, ProvBy.class);
    ensureFails(injector, ALLOW_BINDING, ProvByProvider.class);
  }
  
  public void testProviderMethods() {
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override protected void configure() {
        binder().requireExplicitBindings();
      }
      @SuppressWarnings("unused") @Provides Foo foo() { return new FooImpl(); }
    });
    ensureWorks(injector, Foo.class);
  }
  
  public void testChildInjectorInheritsOption() {
    Injector parent = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        binder().requireExplicitBindings();
        bind(Bar.class);
      }
    });
    ensureWorks(parent, Bar.class);
    ensureFails(parent, FAIL_ALL, FooImpl.class, FooBar.class, Foo.class);
    
    try {
      parent.createChildInjector(new AbstractModule() {
        @Override
        protected void configure() {
          bind(FooBar.class);
        }
      });
      fail("should have failed");
    } catch(CreationException expected) {
      assertContains(expected.getMessage(), "1) " + jitFailed(Foo.class));
      assertTrue(expected.getMessage(), !expected.getMessage().contains("2) "));
    }
    
    Injector child = parent.createChildInjector(new AbstractModule() {
      @Override
      protected void configure() {
        bind(Foo.class).to(FooImpl.class);
      }
    });
    ensureWorks(child, Foo.class, Bar.class);
    ensureFails(child, ALLOW_BINDING, FooImpl.class);
    ensureInChild(parent, FooImpl.class, Foo.class);
    // TODO(sameb): FooBar may or may not be in a child injector, depending on if GC has run.
    // We should fix failed child injectors to remove their contents from the parent blacklist
    // immediately, rather than waiting on GC to do it.
    // FooBar was succesfully inserted into the child injector (and parent blacklist), but then
    // JIT bindings it depended on failed, making the child injector invalid.

    Injector grandchild = child.createChildInjector(new AbstractModule() {
      @Override
      protected void configure() {
        bind(FooBar.class);
      }
    });
    ensureWorks(grandchild, FooBar.class, Foo.class, Bar.class);
    ensureFails(grandchild, ALLOW_BINDING, FooImpl.class);
    ensureFails(child, ALLOW_BINDING, FooImpl.class);
    ensureInChild(parent, FooImpl.class, FooBar.class, Foo.class);    
  }
  
  public void testChildInjectorAddsOption() {
    Injector parent = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        bind(Bar.class);
      }
    });
    int totalParentBindings = parent.getAllBindings().size();
    
    try {
      parent.createChildInjector(new AbstractModule() {
        @Override
        protected void configure() {
          binder().requireExplicitBindings();
          bind(FooBar.class);
        }
      });
      fail("should have failed");
    } catch(CreationException expected) {
      assertContains(expected.getMessage(), "1) " + jitFailed(Foo.class));
      assertTrue(expected.getMessage(), !expected.getMessage().contains("2) "));
    }
    assertEquals(totalParentBindings, parent.getAllBindings().size());
    
    Injector child = parent.createChildInjector(new AbstractModule() {
      @Override
      protected void configure() {
        binder().requireExplicitBindings();
        bind(Foo.class).to(FooImpl.class);
      }
    });
    totalParentBindings++; // creating this child added FooImpl to the parent.
    assertEquals(totalParentBindings, parent.getAllBindings().size());
    ensureWorks(child, Foo.class, Bar.class);
    ensureFails(child, ALLOW_BINDING_PROVIDER, FooImpl.class);
    // Make extra certain that if something tries to inject a FooImpl from child
    // that it fails, even if calling getBinding().getProvider works.. because
    // the binding is built with the parent injector.
    try {
      child.injectMembers(new Object() {
        @SuppressWarnings("unused")
        @Inject
        void inject(FooImpl fooImpl) {}
      });
      fail();
    } catch(ConfigurationException expected) {
      assertContains(expected.getMessage(), "1) " + jitFailed(FooImpl.class));
      assertTrue(expected.getMessage(), !expected.getMessage().contains("2) "));
    }
    
    Injector grandchild = child.createChildInjector(new AbstractModule() {
      @Override
      protected void configure() {
        bind(FooBar.class);
      }
    });
    assertEquals(totalParentBindings, parent.getAllBindings().size());    
    ensureWorks(grandchild, FooBar.class, Foo.class, Bar.class);
    ensureFails(grandchild, ALLOW_BINDING_PROVIDER, FooImpl.class);
    ensureFails(child, ALLOW_BINDING_PROVIDER, FooImpl.class);
    
    // Make sure siblings of children don't inherit each others settings...
    // a new child should be able to get FooImpl.
    child = parent.createChildInjector();
    ensureWorks(child, FooImpl.class);
  }

  public void testPrivateModulesInheritOptions() {
    try {
      Guice.createInjector(new AbstractModule() {
        protected void configure() {
          binder().requireExplicitBindings();
          bind(Foo.class).to(FooImpl.class);
  
          install(new PrivateModule() {
            public void configure() {
              bind(FooBar.class);
              expose(FooBar.class);
            }
          });
        }
      });
      fail("should have failed");
    } catch(CreationException expected) {
      assertContains(expected.getMessage(), "1) " + jitFailed(Bar.class));
      assertTrue(expected.getMessage(), !expected.getMessage().contains("2) "));
    }
    
    Injector injector = Guice.createInjector(new AbstractModule() {
      protected void configure() {
        binder().requireExplicitBindings();

        install(new PrivateModule() {
          public void configure() {
            bind(Foo.class).to(FooImpl.class);
            expose(Foo.class);
          }
        });
      }
    });
    ensureInChild(injector, FooImpl.class);
  }
  
  public void testPrivateModuleAddsOption() {
    try {
      Guice.createInjector(new AbstractModule() {
        protected void configure() {
          bind(Foo.class).to(FooImpl.class);
  
          // Fails because FooBar is in the private module,
          // and it wants Bar, but Bar would be JIT.
          install(new PrivateModule() {
            public void configure() {
              binder().requireExplicitBindings();
              bind(FooBar.class);
              expose(FooBar.class);
            }
          });
        }
      });
      fail("should have failed");
    } catch(CreationException expected) {
      assertContains(expected.getMessage(), "1) " + jitFailed(Bar.class));
      assertTrue(expected.getMessage(), !expected.getMessage().contains("2) "));
    }
  }

  public void testPrivateModuleSiblingsDontShareOption() {
    Guice.createInjector(new AbstractModule() {
      protected void configure() {
        bind(Foo.class).to(FooImpl.class);

        install(new PrivateModule() {
          public void configure() {
            binder().requireExplicitBindings();
          }
        });

        // This works, even though Bar is JIT,
        // because the requireExplicitBindings isn't shared
        // between sibling private modules.
        install(new PrivateModule() {
          public void configure() {
            bind(FooBar.class);
            expose(FooBar.class);
          }
        });
      }
    });
  }  

  public void testTypeLiteralsCanBeInjected() {
    Injector injector = Guice.createInjector(new AbstractModule() {
        @Override protected void configure() {
          binder().requireExplicitBindings();
          bind(new TypeLiteral<WantsTypeLiterals<String>>() {});
          bind(new TypeLiteral<Set<String>>() {}).toInstance(of("bar"));
        }
      });

    WantsTypeLiterals<String> foo = injector.getInstance(new Key<WantsTypeLiterals<String>>() {});
    assertEquals(foo.literal.getRawType(), String.class);
    assertEquals(of("bar"), foo.set);
  }
  
  public void testMembersInjectorsCanBeInjected() {
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override protected void configure() {
        binder().requireExplicitBindings();
      }
      
      @Provides String data(MembersInjector<String> mi) {
        String data = "foo";
        mi.injectMembers(data);
        return data;
      }
    });

    String data = injector.getInstance(String.class);
    assertEquals("foo", data);
  }
  
  private void ensureWorks(Injector injector, Class<?>... classes) {
    for(int i = 0; i < classes.length; i++) {
      injector.getInstance(classes[i]);
      injector.getProvider(classes[i]).get();
      injector.getBinding(classes[i]).getProvider().get();
    }
  }
  
  enum GetBindingCheck { FAIL_ALL, ALLOW_BINDING, ALLOW_BINDING_PROVIDER }
  private void ensureFails(Injector injector, GetBindingCheck getBinding, Class<?>... classes) {
    for(int i = 0; i < classes.length; i++) {      
      try { 
        injector.getInstance(classes[i]);
        fail("should have failed tring to retrieve class: " + classes[i]);
      } catch(ConfigurationException expected) {
        assertContains(expected.getMessage(), "1) " + jitFailed(classes[i]));
        assertTrue(expected.getMessage(), !expected.getMessage().contains("2) "));
      }
      
      try { 
        injector.getProvider(classes[i]);
        fail("should have failed tring to retrieve class: " + classes[i]);
      } catch(ConfigurationException expected) {
        assertContains(expected.getMessage(), "1) " + jitFailed(classes[i]));
        assertTrue(expected.getMessage(), !expected.getMessage().contains("2) "));
      }
      
      if (getBinding == GetBindingCheck.ALLOW_BINDING
          || getBinding == GetBindingCheck.ALLOW_BINDING_PROVIDER) {
        Binding<?> binding = injector.getBinding(classes[i]);
        try {
          binding.getProvider();
          if (getBinding != GetBindingCheck.ALLOW_BINDING_PROVIDER) {
            fail("should have failed trying to retrieve class: " + classes[i]);
          }
        } catch(ConfigurationException expected) {
          if (getBinding == GetBindingCheck.ALLOW_BINDING_PROVIDER) {
            throw expected;
          }
          assertContains(expected.getMessage(), "1) " + jitFailed(classes[i]));
          assertTrue(expected.getMessage(), !expected.getMessage().contains("2) "));
        }
      } else {
        try {
          injector.getBinding(classes[i]);
          fail("should have failed tring to retrieve class: " + classes[i]);          
        } catch(ConfigurationException expected) {
          assertContains(expected.getMessage(), "1) " + jitFailed(classes[i]));
          assertTrue(expected.getMessage(), !expected.getMessage().contains("2) "));
        }
      }
    }
  }
  
  private void ensureInChild(Injector injector, Class<?>... classes) {
    for(int i = 0; i < classes.length; i++) {      
      try { 
        injector.getInstance(classes[i]);
        fail("should have failed tring to retrieve class: " + classes[i]);
      } catch(ConfigurationException expected) {
        assertContains(expected.getMessage(), "1) " + inChildMessage(classes[i]));
        assertTrue(expected.getMessage(), !expected.getMessage().contains("2) "));
      }
      
      try { 
        injector.getProvider(classes[i]);
        fail("should have failed tring to retrieve class: " + classes[i]);
      } catch(ConfigurationException expected) {
        assertContains(expected.getMessage(), "1) " + inChildMessage(classes[i]));
        assertTrue(expected.getMessage(), !expected.getMessage().contains("2) "));
      }
      
      try {
        injector.getBinding(classes[i]);
        fail("should have failed tring to retrieve class: " + classes[i]);          
      } catch(ConfigurationException expected) {
        assertContains(expected.getMessage(), "1) " + inChildMessage(classes[i]));
        assertTrue(expected.getMessage(), !expected.getMessage().contains("2) "));
      }
    }
  }
  
  private static interface Foo {}
  private static class FooImpl implements Foo {}
  @Singleton private static class ScopedFooImpl implements Foo {}
  private static class WantsScopedFooImpl {
    @SuppressWarnings("unused") @Inject ScopedFooImpl scopedFoo;
  }
  private static class Bar {}
  private static class FooBar {
    @SuppressWarnings("unused") @Inject Foo foo;
    @SuppressWarnings("unused") @Inject Bar bar;
  }
  private static class ProviderFooBar {
    @SuppressWarnings("unused") @Inject Provider<Foo> foo;
    @SuppressWarnings("unused") @Inject Provider<Bar> bar;
  }
  private static class FooProvider implements Provider<Foo> {
    public Foo get() {
      return new FooImpl();
    }
  }

  @ImplementedBy(ImplByImpl.class)
  private static interface ImplBy {}
  private static class ImplByImpl implements ImplBy {}
  
  @ImplementedBy(ImplByScopedImpl.class)
  private static interface ImplByScoped {}
  @Singleton
  private static class ImplByScopedImpl implements ImplByScoped {}  

  @ProvidedBy(ProvByProvider.class)
  private static interface ProvBy {}
  private static class ProvByProvider implements Provider<ProvBy> {
    public ProvBy get() {
      return new ProvBy() {};
    }
  }
  
  private static class WantsTypeLiterals<T> {
    TypeLiteral<T> literal;
    Set<T> set;
    
    @Inject WantsTypeLiterals(TypeLiteral<T> literal, Set<T> set) {
      this.literal = literal;
      this.set = set;
      
    }
  }
}
