/**
 * 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.Asserts.assertNotSerializable;
import com.google.inject.internal.Iterables;
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 java.io.IOException;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.concurrent.Callable;
import junit.framework.TestCase;

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

  Provider<Foo> fooProvider;

  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() {
        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());
      assertContains(e.getMessage(),
          "1) No implementation for java.lang.Runnable was bound.",
          "at " + getClass().getName(),
          "2) No implementation for " + Comparator.class.getName() + " was bound.",
          "at " + getClass().getName(),
          "3) No implementation for java.util.concurrent.Callable<java.lang.String> was bound.",
          "at " + getClass().getName(),
          "4) No implementation for java.util.Date annotated with @"
              + Named.class.getName() + "(value=date) was bound.",
          "at " + getClass().getName());
    }
  }

  public void testDuplicateBindings() {
    try {
      Guice.createInjector(new AbstractModule() {
        protected void configure() {
          bind(JustAClass.class);
          bind(JustAClass.class);
        }
      });
      fail();
    } catch (CreationException expected) {
      assertContains(expected.getMessage(), "A binding to " + JustAClass.class.getName(),
          " was already configured at " + BinderTest.class.getName(), ".configure(",
          "at " + BinderTest.class.getName(), ".configure(BinderTest.java:");
    }
  }

  public void testMissingDependency() {
    try {
      Guice.createInjector(new AbstractModule() {
        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(), ".configure(BinderTest.java:");
    }
  }

  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(), ".configure(BinderTest.java:");
    }
  }

  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() {
      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() {
        protected void configure() {
          bind(String[].class).toInstance(strings);
          bind(new TypeLiteral<String[]>() {}).toInstance(strings);
        }
      });
      fail();
    } catch (CreationException expected) {
      assertContains(expected.getMessage(),
          "1) A binding to java.lang.String[] was already configured at " + getClass().getName(),
          "at " + getClass().getName(), ".configure(BinderTest.java:");
      assertContains(expected.getMessage(), "1 error");
    }
  }

  /**
   * 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() {
      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() {
        protected void configure() {
          addError(message);
        }
      });
      fail();
    } catch (CreationException expected) {
      assertSame(message, Iterables.getOnlyElement(expected.getErrorMessages()));
    }
  }

  public void testBindingToProvider() {
    try {
      Guice.createInjector(new AbstractModule() {
        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(), "configure(BinderTest.java:");
    }
  }

  public void testCannotBindToGuiceTypes() {
    final Named red = Names.named("red");

    try {
      Guice.createInjector(new AbstractModule() {
        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(TypeLiteral.class).annotatedWith(red).toProvider(Providers.<TypeLiteral>of(null));
          bind(new TypeLiteral<Key<String>>() {}).toProvider(Providers.<Key<String>>of(null));
        }
      });
      fail();
    } catch (CreationException expected) {
      assertContains(expected.getMessage(),
          "Binding to core guice framework type is not allowed: AbstractModule.",
          "Binding to core guice framework type is not allowed: Binder.",
          "Binding to core guice framework type is not allowed: Binding.",
          "Binding to core guice framework type is not allowed: Injector.",
          "Binding to core guice framework type is not allowed: Key.",
          "Binding to core guice framework type is not allowed: Module.",
          "Binding to Provider is not allowed.",
          "Binding to core guice framework type is not allowed: Scope.",
          "Binding to core guice framework type is not allowed: TypeLiteral.",
          "Binding to core guice framework type is not allowed: Key.");
    }
  }

  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 {}


//  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());
    }
  }
}
