/**
 * Copyright (C) 2009 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.assistedinject;

import static com.google.inject.Asserts.assertContains;

import com.google.inject.AbstractModule;
import com.google.inject.CreationException;
import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.Provides;
import com.google.inject.TypeLiteral;
import com.google.inject.internal.util.Iterables;
import com.google.inject.name.Named;
import com.google.inject.name.Names;
import com.google.inject.spi.Message;

import junit.framework.TestCase;

import java.awt.*;
import java.util.Collection;

public class FactoryModuleBuilderTest extends TestCase {

  public void testImplicitForwardingAssistedBindingFailsWithInterface() {
    try {
      Guice.createInjector(new AbstractModule() {
        @Override
        protected void configure() {
          bind(Car.class).to(Golf.class);
          install(new FactoryModuleBuilder().build(ColoredCarFactory.class));
        }
      });
      fail();
    } catch (CreationException ce) {
      assertContains(
          ce.getMessage(), "1) " + Car.class.getName() + " is an interface, not a concrete class.",
          "Unable to create AssistedInject factory.",
          "while locating " + Car.class.getName(),
          "at " + ColoredCarFactory.class.getName() + ".create(");
      assertEquals(1, ce.getErrorMessages().size());
    }
  }
  
  public void testImplicitForwardingAssistedBindingFailsWithAbstractClass() {
    try {
      Guice.createInjector(new AbstractModule() {
        @Override
        protected void configure() {
          bind(AbstractCar.class).to(ArtCar.class);
          install(new FactoryModuleBuilder().build(ColoredAbstractCarFactory.class));
        }
      });
      fail();
    } catch (CreationException ce) {
      assertContains(
          ce.getMessage(), "1) " + AbstractCar.class.getName() + " is abstract, not a concrete class.",
          "Unable to create AssistedInject factory.",
          "while locating " + AbstractCar.class.getName(),
          "at " + ColoredAbstractCarFactory.class.getName() + ".create(");
      assertEquals(1, ce.getErrorMessages().size());
    }
  }

  public void testImplicitForwardingAssistedBindingCreatesNewObjects() {
    final Mustang providedMustang = new Mustang(Color.BLUE);
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override protected void configure() {
        install(new FactoryModuleBuilder().build(MustangFactory.class));
      }
      @Provides Mustang provide() { return providedMustang; }
    });
    assertSame(providedMustang, injector.getInstance(Mustang.class));
    MustangFactory factory = injector.getInstance(MustangFactory.class);
    Mustang created = factory.create(Color.GREEN);
    assertNotSame(providedMustang, created);
    assertEquals(Color.BLUE, providedMustang.color);
    assertEquals(Color.GREEN, created.color);
  }

  public void testExplicitForwardingAssistedBindingFailsWithInterface() {
    try {
      Guice.createInjector(new AbstractModule() {
        @Override
        protected void configure() {
          bind(Volkswagen.class).to(Golf.class);
          install(new FactoryModuleBuilder()
            .implement(Car.class, Volkswagen.class)
            .build(ColoredCarFactory.class));
        }
      });
      fail();
    } catch (CreationException ce) {
      assertContains(
          ce.getMessage(), "1) " + Volkswagen.class.getName() + " is an interface, not a concrete class.",
          "Unable to create AssistedInject factory.",
          "while locating " + Volkswagen.class.getName(),
          "while locating " + Car.class.getName(),
          "at " + ColoredCarFactory.class.getName() + ".create(");
      assertEquals(1, ce.getErrorMessages().size());
    }
  }

  public void testExplicitForwardingAssistedBindingFailsWithAbstractClass() {
    try {
      Guice.createInjector(new AbstractModule() {
        @Override
        protected void configure() {
          bind(AbstractCar.class).to(ArtCar.class);
          install(new FactoryModuleBuilder()
            .implement(Car.class, AbstractCar.class)
            .build(ColoredCarFactory.class));
        }
      });
      fail();
    } catch (CreationException ce) {
      assertContains(
          ce.getMessage(), "1) " + AbstractCar.class.getName() + " is abstract, not a concrete class.",
          "Unable to create AssistedInject factory.",
          "while locating " + AbstractCar.class.getName(),
          "while locating " + Car.class.getName(),
          "at " + ColoredCarFactory.class.getName() + ".create(");
      assertEquals(1, ce.getErrorMessages().size());
    }
  }
  
  public void testExplicitForwardingAssistedBindingCreatesNewObjects() {
    final Mustang providedMustang = new Mustang(Color.BLUE);
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override protected void configure() {
        install(new FactoryModuleBuilder().implement(Car.class, Mustang.class).build(
            ColoredCarFactory.class));
      }
      @Provides Mustang provide() { return providedMustang; }
    });
    assertSame(providedMustang, injector.getInstance(Mustang.class));
    ColoredCarFactory factory = injector.getInstance(ColoredCarFactory.class);
    Mustang created = (Mustang)factory.create(Color.GREEN);
    assertNotSame(providedMustang, created);
    assertEquals(Color.BLUE, providedMustang.color);
    assertEquals(Color.GREEN, created.color);
  }

  public void testAnnotatedAndParentBoundReturnValue() {
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override protected void configure() {
        bind(Car.class).to(Golf.class);

        bind(Integer.class).toInstance(911);
        bind(Double.class).toInstance(5.0d);
        install(new FactoryModuleBuilder()
            .implement(Car.class, Names.named("german"), Beetle.class)
            .implement(Car.class, Names.named("american"), Mustang.class)
            .build(AnnotatedVersatileCarFactory.class));
      }
    });

    AnnotatedVersatileCarFactory factory = injector.getInstance(AnnotatedVersatileCarFactory.class);
    assertTrue(factory.getGermanCar(Color.BLACK) instanceof Beetle);
    assertTrue(injector.getInstance(Car.class) instanceof Golf);
  }

  public void testParentBoundReturnValue() {
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override protected void configure() {
        bind(Car.class).to(Golf.class);
        bind(Double.class).toInstance(5.0d);
        install(new FactoryModuleBuilder()
            .implement(Car.class, Mustang.class)
            .build(ColoredCarFactory.class));
      }
    });

    ColoredCarFactory factory = injector.getInstance(ColoredCarFactory.class);
    assertTrue(factory.create(Color.RED) instanceof Mustang);
    assertTrue(injector.getInstance(Car.class) instanceof Golf);
  }

  public void testConfigureAnnotatedReturnValue() {
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override protected void configure() {
        install(new FactoryModuleBuilder()
            .implement(Car.class, Names.named("german"), Beetle.class)
            .implement(Car.class, Names.named("american"), Mustang.class)
            .build(AnnotatedVersatileCarFactory.class));
      }
    });

    AnnotatedVersatileCarFactory factory = injector.getInstance(AnnotatedVersatileCarFactory.class);
    assertTrue(factory.getGermanCar(Color.GRAY) instanceof Beetle);
    assertTrue(factory.getAmericanCar(Color.BLACK) instanceof Mustang);
  }

  public void testNoBindingAssistedInject() {
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        install(new FactoryModuleBuilder().build(MustangFactory.class));
      }
    });

    MustangFactory factory = injector.getInstance(MustangFactory.class);

    Mustang mustang = factory.create(Color.BLUE);
    assertEquals(Color.BLUE, mustang.color);
  }

  public void testBindingAssistedInject() {
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        install(new FactoryModuleBuilder()
            .implement(Car.class, Mustang.class)
            .build(ColoredCarFactory.class));
      }
    });

    ColoredCarFactory factory = injector.getInstance(ColoredCarFactory.class);

    Mustang mustang = (Mustang) factory.create(Color.BLUE);
    assertEquals(Color.BLUE, mustang.color);
  }

  public void testMultipleReturnTypes() {
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        bind(Double.class).toInstance(5.0d);
        install(new FactoryModuleBuilder().build(VersatileCarFactory.class));
      }
    });

    VersatileCarFactory factory = injector.getInstance(VersatileCarFactory.class);

    Mustang mustang = factory.getMustang(Color.RED);
    assertEquals(Color.RED, mustang.color);

    Beetle beetle = factory.getBeetle(Color.GREEN);
    assertEquals(Color.GREEN, beetle.color);
  }
  
  public void testParameterizedClassesWithNoImplements() {
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        install(new FactoryModuleBuilder().build(new TypeLiteral<Foo.Factory<String>>() {}));
      }
    });
    
    Foo.Factory<String> factory = injector.getInstance(Key.get(new TypeLiteral<Foo.Factory<String>>() {}));
    @SuppressWarnings("unused")
    Foo<String> foo = factory.create(new Bar());
  }
  
  public void testGenericErrorMessageMakesSense() {
    try {
      Guice.createInjector(new AbstractModule() {
        @Override
        protected void configure() {
         install(new FactoryModuleBuilder().build(Key.get(Foo.Factory.class))); 
        }
      });
      fail();
    } catch(CreationException ce ) {
      // Assert not only that it's the correct message, but also that it's the *only* message.
      Collection<Message> messages = ce.getErrorMessages();
      assertEquals(
          Foo.Factory.class.getName() + " cannot be used as a key; It is not fully specified.", 
          Iterables.getOnlyElement(messages).getMessage());
    }
  }

  interface Car {}

  interface Volkswagen extends Car {}

  interface ColoredCarFactory {
    Car create(Color color);
  }

  interface MustangFactory {
    Mustang create(Color color);
  }

  interface VersatileCarFactory {
    Mustang getMustang(Color color);
    Beetle getBeetle(Color color);
  }

  interface AnnotatedVersatileCarFactory {
    @Named("german") Car getGermanCar(Color color);
    @Named("american") Car getAmericanCar(Color color);
  }

  public static class Golf implements Volkswagen {}

  public static class Mustang implements Car {
    private final Color color;
    @Inject
    public Mustang(@Assisted Color color) {
      this.color = color;
    }
  }

  public static class Beetle implements Car {
    private final Color color;
    @Inject
    public Beetle(@Assisted Color color) {
      this.color = color;
    }
  }
  
  public static class Foo<E> {
    static interface Factory<E> {
      Foo<E> create(Bar bar);
    }
    @Inject Foo(@Assisted Bar bar, Baz<E> baz) {}
  }
  
  public static class Bar {}
  public static class Baz<E> {}
  
  abstract static class AbstractCar implements Car {}  
  interface ColoredAbstractCarFactory {
    AbstractCar create(Color color);
  }  
  public static class ArtCar extends AbstractCar {}
  

}
