/**
 * Copyright (C) 2008 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 static com.google.inject.Asserts.assertEqualsBothWays;

import com.google.inject.AbstractModule;
import com.google.inject.ConfigurationException;
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.Provider;
import com.google.inject.Stage;
import com.google.inject.TypeLiteral;
import com.google.inject.assistedinject.FactoryProvider2Test.Equals.ComparisonMethod;
import com.google.inject.assistedinject.FactoryProvider2Test.Equals.Impl;
import com.google.inject.matcher.Matchers;
import com.google.inject.name.Named;
import com.google.inject.name.Names;

import junit.framework.TestCase;

import java.util.Collection;
import java.util.Collections;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;

@SuppressWarnings("deprecation")
public class FactoryProvider2Test extends TestCase {

  private enum Color { BLUE, GREEN, RED, GRAY, BLACK, ORANGE, PINK }
  
  public void testAssistedFactory() {
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        bind(Double.class).toInstance(5.0d);
        bind(ColoredCarFactory.class).toProvider(
            FactoryProvider.newFactory(ColoredCarFactory.class, Mustang.class));
      }
    });
    ColoredCarFactory carFactory = injector.getInstance(ColoredCarFactory.class);

    Mustang blueMustang = (Mustang) carFactory.create(Color.BLUE);
    assertEquals(Color.BLUE, blueMustang.color);
    assertEquals(5.0d, blueMustang.engineSize);

    Mustang redMustang = (Mustang) carFactory.create(Color.RED);
    assertEquals(Color.RED, redMustang.color);
    assertEquals(5.0d, redMustang.engineSize);
  }

  public void testAssistedFactoryWithAnnotations() {
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        bind(int.class).annotatedWith(Names.named("horsePower")).toInstance(250);
        bind(int.class).annotatedWith(Names.named("modelYear")).toInstance(1984);
        bind(ColoredCarFactory.class).toProvider(
            FactoryProvider.newFactory(ColoredCarFactory.class, Camaro.class));
      }
    });

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

    Camaro blueCamaro = (Camaro) carFactory.create(Color.BLUE);
    assertEquals(Color.BLUE, blueCamaro.color);
    assertEquals(1984, blueCamaro.modelYear);
    assertEquals(250, blueCamaro.horsePower);

    Camaro redCamaro = (Camaro) carFactory.create(Color.RED);
    assertEquals(Color.RED, redCamaro.color);
    assertEquals(1984, redCamaro.modelYear);
    assertEquals(250, redCamaro.horsePower);
  }

  public interface Car {}

  interface ColoredCarFactory {
    Car create(Color color);
  }

  public static class Mustang implements Car {
    private final double engineSize;
    private final Color color;

    @Inject
    public Mustang(double engineSize, @Assisted Color color) {
      this.engineSize = engineSize;
      this.color = color;
    }

    public void drive() {}
  }

  public static class Camaro implements Car {
    private final int horsePower;
    private final int modelYear;
    private final Color color;

    @Inject
    public Camaro(
        @Named("horsePower") int horsePower,
        @Named("modelYear") int modelYear,
        @Assisted Color color) {
      this.horsePower = horsePower;
      this.modelYear = modelYear;
      this.color = color;
    }
  }

  interface SummerCarFactory {
    Car create(Color color, boolean convertable);
  }

  public void testFactoryUsesInjectedConstructor() {
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        bind(float.class).toInstance(140f);
        bind(SummerCarFactory.class).toProvider(
            FactoryProvider.newFactory(SummerCarFactory.class, Corvette.class));
      }
    });

    SummerCarFactory carFactory = injector.getInstance(SummerCarFactory.class);

    Corvette redCorvette = (Corvette) carFactory.create(Color.RED, false);
    assertEquals(Color.RED, redCorvette.color);
    assertEquals(140f, redCorvette.maxMph);
    assertFalse(redCorvette.isConvertable);
  }

  public static class Corvette implements Car {
    private boolean isConvertable;
    private Color color;
    private float maxMph;

    @SuppressWarnings("unused")
    public Corvette(Color color, boolean isConvertable) {
      throw new IllegalStateException("Not an @AssistedInject constructor");
    }

    @Inject
    public Corvette(@Assisted Color color, Float maxMph, @Assisted boolean isConvertable) {
      this.isConvertable = isConvertable;
      this.color = color;
      this.maxMph = maxMph;
    }
  }

  public void testConstructorDoesntNeedAllFactoryMethodArguments() {
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        bind(SummerCarFactory.class).toProvider(
            FactoryProvider.newFactory(SummerCarFactory.class, Beetle.class));
      }
    });
    SummerCarFactory factory = injector.getInstance(SummerCarFactory.class);

    Beetle beetle = (Beetle) factory.create(Color.RED, true);
    assertSame(Color.RED, beetle.color);
  }

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

  public void testMethodsAndFieldsGetInjected() {
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        bind(String.class).toInstance("turbo");
        bind(int.class).toInstance(911);
        bind(double.class).toInstance(50000d);
        bind(ColoredCarFactory.class).toProvider(
            FactoryProvider.newFactory(ColoredCarFactory.class, Porsche.class));
      }
    });
    ColoredCarFactory carFactory = injector.getInstance(ColoredCarFactory.class);

    Porsche grayPorsche = (Porsche) carFactory.create(Color.GRAY);
    assertEquals(Color.GRAY, grayPorsche.color);
    assertEquals(50000d, grayPorsche.price);
    assertEquals(911, grayPorsche.model);
    assertEquals("turbo", grayPorsche.name);
  }

  public static class Porsche implements Car {
    private final Color color;
    private final double price;
    private @Inject String name;
    private int model;

    @Inject
    public Porsche(@Assisted Color color, double price) {
      this.color = color;
      this.price = price;
    }

    @Inject void setModel(int model) {
      this.model = model;
    }
  }

  public void testProviderInjection() {
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        bind(String.class).toInstance("trans am");
        bind(ColoredCarFactory.class).toProvider(
            FactoryProvider.newFactory(ColoredCarFactory.class, Firebird.class));
      }
    });
    ColoredCarFactory carFactory = injector.getInstance(ColoredCarFactory.class);

    Firebird blackFirebird = (Firebird) carFactory.create(Color.BLACK);
    assertEquals(Color.BLACK, blackFirebird.color);
    assertEquals("trans am", blackFirebird.modifiersProvider.get());
  }

  public static class Firebird implements Car {
    private final Provider<String> modifiersProvider;
    private final Color color;

    @Inject
    public Firebird(Provider<String> modifiersProvider, @Assisted Color color) {
      this.modifiersProvider = modifiersProvider;
      this.color = color;
    }
  }
  
  public void testAssistedProviderInjection() {
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        bind(String.class).toInstance("trans am");
        bind(ColoredCarFactory.class).toProvider(
            FactoryProvider.newFactory(ColoredCarFactory.class, Flamingbird.class));
      }
    });
    ColoredCarFactory carFactory = injector.getInstance(ColoredCarFactory.class);

    Flamingbird flamingbird = (Flamingbird) carFactory.create(Color.BLACK);
    assertEquals(Color.BLACK, flamingbird.colorProvider.get());
    assertEquals("trans am", flamingbird.modifiersProvider.get());
    
    Flamingbird flamingbird2 = (Flamingbird) carFactory.create(Color.RED);
    assertEquals(Color.RED, flamingbird2.colorProvider.get());
    assertEquals("trans am", flamingbird2.modifiersProvider.get());
    // Make sure the original flamingbird is black still.
    assertEquals(Color.BLACK, flamingbird.colorProvider.get());
  }  
  
  public static class Flamingbird implements Car {
    private final Provider<String> modifiersProvider;
    private final Provider<Color> colorProvider;

    @Inject
    public Flamingbird(Provider<String> modifiersProvider, @Assisted Provider<Color> colorProvider) {
      this.modifiersProvider = modifiersProvider;
      this.colorProvider = colorProvider;
    }
  }

  public void testTypeTokenInjection() {
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        bind(new TypeLiteral<Set<String>>() {}).toInstance(Collections.singleton("Flux Capacitor"));
        bind(new TypeLiteral<Set<Integer>>() {}).toInstance(Collections.singleton(88));
        bind(ColoredCarFactory.class).toProvider(
            FactoryProvider.newFactory(ColoredCarFactory.class, DeLorean.class));
      }
    });
    ColoredCarFactory carFactory = injector.getInstance(ColoredCarFactory.class);

    DeLorean deLorean = (DeLorean) carFactory.create(Color.GRAY);
    assertEquals(Color.GRAY, deLorean.color);
    assertEquals("Flux Capacitor", deLorean.features.iterator().next());
    assertEquals(new Integer(88), deLorean.featureActivationSpeeds.iterator().next());
  }

  public static class DeLorean implements Car {
    private final Set<String> features;
    private final Set<Integer> featureActivationSpeeds;
    private final Color color;

    @Inject
    public DeLorean(
        Set<String> extraFeatures, Set<Integer> featureActivationSpeeds, @Assisted Color color) {
      this.features = extraFeatures;
      this.featureActivationSpeeds = featureActivationSpeeds;
      this.color = color;
    }
  }

  public void testTypeTokenProviderInjection() {
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        bind(new TypeLiteral<Set<String>>() { }).toInstance(Collections.singleton("Datsun"));
        bind(ColoredCarFactory.class).toProvider(
            FactoryProvider.newFactory(ColoredCarFactory.class, Z.class));
      }
    });
    ColoredCarFactory carFactory = injector.getInstance(ColoredCarFactory.class);

    Z orangeZ = (Z) carFactory.create(Color.ORANGE);
    assertEquals(Color.ORANGE, orangeZ.color);
    assertEquals("Datsun", orangeZ.manufacturersProvider.get().iterator().next());
  }

  public static class Z implements Car {
    private final Provider<Set<String>> manufacturersProvider;
    private final Color color;

    @Inject
    public Z(Provider<Set<String>> manufacturersProvider, @Assisted Color color) {
      this.manufacturersProvider = manufacturersProvider;
      this.color = color;
    }
  }

  public static class Prius implements Car {
    final Color color;

    @Inject
    private Prius(@Assisted Color color) {
      this.color = color;
    }
  }

  public void testAssistInjectionInNonPublicConstructor() {
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        bind(ColoredCarFactory.class).toProvider(
            FactoryProvider.newFactory(ColoredCarFactory.class, Prius.class));
      }
    });
    Prius prius = (Prius) injector.getInstance(ColoredCarFactory.class).create(Color.ORANGE);
    assertEquals(prius.color, Color.ORANGE);
  }

  public static class ExplodingCar implements Car {
    @Inject
    public ExplodingCar(@SuppressWarnings("unused") @Assisted Color color) {
      throw new IllegalStateException("kaboom!");
    }
  }

  public void testExceptionDuringConstruction() {
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        bind(ColoredCarFactory.class).toProvider(
            FactoryProvider.newFactory(ColoredCarFactory.class, ExplodingCar.class));
      }
    });
    try {
      injector.getInstance(ColoredCarFactory.class).create(Color.ORANGE);
      fail();
    } catch (IllegalStateException e) {
      assertEquals("kaboom!", e.getMessage());
    }
  }

  public static class DefectiveCar implements Car {
    @Inject
    public DefectiveCar() throws ExplosionException {
      throw new ExplosionException();
    }
  }

  public static class ExplosionException extends Exception { }
  public static class FireException extends Exception { }

  public interface DefectiveCarFactoryWithNoExceptions {
    Car createCar();
  }

  public interface DefectiveCarFactory {
    Car createCar() throws FireException;
  }

  public interface CorrectDefectiveCarFactory {
    Car createCar() throws FireException, ExplosionException;
  }

  public void testConstructorExceptionsAreThrownByFactory() {
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        bind(CorrectDefectiveCarFactory.class).toProvider(
            FactoryProvider.newFactory(CorrectDefectiveCarFactory.class, DefectiveCar.class));
      }
    });
    try {
      injector.getInstance(CorrectDefectiveCarFactory.class).createCar();
      fail();
    } catch (FireException e) {
      fail();
    } catch (ExplosionException expected) {
    }
  }

  public static class WildcardCollection {

    public interface Factory {
      WildcardCollection create(Collection<?> items);
    }

    @Inject
    public WildcardCollection(@SuppressWarnings("unused") @Assisted Collection<?> items) { }
  }

  public void testWildcardGenerics() {
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        bind(WildcardCollection.Factory.class).toProvider(
            FactoryProvider.newFactory(WildcardCollection.Factory.class, WildcardCollection.class));
      }
    });
    WildcardCollection.Factory factory = injector.getInstance(WildcardCollection.Factory.class);
    factory.create(Collections.emptyList());
  }

  public static class SteeringWheel {}

  public static class Fiat implements Car {
    private final SteeringWheel steeringWheel;
    private final Color color;

    @Inject
    public Fiat(SteeringWheel steeringWheel, @Assisted Color color) {
      this.steeringWheel = steeringWheel;
      this.color = color;
    }
  }

  public void testFactoryWithImplicitBindings() {
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        bind(ColoredCarFactory.class).toProvider(
            FactoryProvider.newFactory(ColoredCarFactory.class, Fiat.class));
      }
    });

    ColoredCarFactory coloredCarFactory = injector.getInstance(ColoredCarFactory.class);
    Fiat fiat = (Fiat) coloredCarFactory.create(Color.GREEN);
    assertEquals(Color.GREEN, fiat.color);
    assertNotNull(fiat.steeringWheel);
  }

  public void testFactoryFailsWithMissingBinding() {
    try {
      Guice.createInjector(new AbstractModule() {
        @Override protected void configure() {
          bind(ColoredCarFactory.class).toProvider(
              FactoryProvider.newFactory(ColoredCarFactory.class, Mustang.class));
        }
      });
      fail();
    } catch (CreationException expected) {
      assertContains(expected.getMessage(),
          "Could not find a suitable constructor in java.lang.Double.",
          "at " + ColoredCarFactory.class.getName() + ".create(FactoryProvider2Test.java");
    }
  }
  
  public void testFactoryFailsWithMissingBindingInToolStage() {
    try {
      Guice.createInjector(Stage.TOOL, new AbstractModule() {
        @Override protected void configure() {
          bind(ColoredCarFactory.class).toProvider(
              FactoryProvider.newFactory(ColoredCarFactory.class, Mustang.class));
        }
      });
      fail();
    } catch (CreationException expected) {
      assertContains(expected.getMessage(),
          "Could not find a suitable constructor in java.lang.Double.",
          "at " + ColoredCarFactory.class.getName() + ".create(FactoryProvider2Test.java");
    }
  }

  public void testMethodsDeclaredInObject() {
    Injector injector = Guice.createInjector(new AbstractModule() {
        @Override protected void configure() {
          bind(Double.class).toInstance(5.0d);
          bind(ColoredCarFactory.class).toProvider(
              FactoryProvider.newFactory(ColoredCarFactory.class, Mustang.class));
        }
      });

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

    assertEqualsBothWays(carFactory, carFactory);
  }

  static class Subaru implements Car {
    @Inject @Assisted Provider<Color> colorProvider;
  }

  public void testInjectingProviderOfParameter() {
    Injector injector = Guice.createInjector(new AbstractModule() {
        @Override protected void configure() {
          bind(ColoredCarFactory.class).toProvider(
              FactoryProvider.newFactory(ColoredCarFactory.class, Subaru.class));
        }
      });

    ColoredCarFactory carFactory = injector.getInstance(ColoredCarFactory.class);
    Subaru subaru = (Subaru) carFactory.create(Color.RED);

    assertSame(Color.RED, subaru.colorProvider.get());
    assertSame(Color.RED, subaru.colorProvider.get());
    
    Subaru sedan  = (Subaru) carFactory.create(Color.BLUE);
    assertSame(Color.BLUE, sedan.colorProvider.get());
    assertSame(Color.BLUE, sedan.colorProvider.get());
    
    // and make sure the subaru is still red
    assertSame(Color.RED, subaru.colorProvider.get());
  }

  public void testInjectingNullParameter() {
    Injector injector = Guice.createInjector(new AbstractModule() {
        @Override protected void configure() {
          bind(ColoredCarFactory.class).toProvider(
              FactoryProvider.newFactory(ColoredCarFactory.class, Subaru.class));
        }
      });

    ColoredCarFactory carFactory = injector.getInstance(ColoredCarFactory.class);
    Subaru subaru = (Subaru) carFactory.create(null);

    assertNull(subaru.colorProvider.get());
    assertNull(subaru.colorProvider.get());
  }

  interface ProviderBasedColoredCarFactory {
    Car createCar(Provider<Color> colorProvider, Provider<String> stringProvider);
    Mustang createMustang(@Assisted("color") Provider<Color> colorProvider);
  }

  public void testAssistedProviderIsDisallowed() {
    try {
      Guice.createInjector(new AbstractModule() {
          @Override protected void configure() {
            bind(ProviderBasedColoredCarFactory.class).toProvider(
                FactoryProvider.newFactory(ProviderBasedColoredCarFactory.class, Subaru.class));
          }
      });
      fail();
    } catch (CreationException expected) {
      assertEquals(expected.getMessage(), 4, expected.getErrorMessages().size());
      // Assert each method individually, because JDK7 doesn't guarantee method ordering.
      assertContains(expected.getMessage(),
          ") A Provider may not be a type in a factory method of an AssistedInject."
            + "\n  Offending instance is parameter [1] with key"
            + " [com.google.inject.Provider<" + Color.class.getName() + ">] on method ["
            + ProviderBasedColoredCarFactory.class.getName() + ".createCar()]");
      assertContains(expected.getMessage(),
          ") A Provider may not be a type in a factory method of an AssistedInject."
            + "\n  Offending instance is parameter [2] with key"
            + " [com.google.inject.Provider<java.lang.String>] on method ["
            + ProviderBasedColoredCarFactory.class.getName() + ".createCar()]");
      assertContains(expected.getMessage(),
          ") A Provider may not be a type in a factory method of an AssistedInject."
            + "\n  Offending instance is parameter [1] with key"
            + " [com.google.inject.Provider<" + Color.class.getName() + ">"
            + " annotated with @com.google.inject.assistedinject.Assisted(value=color)]"
            + " on method [" + ProviderBasedColoredCarFactory.class.getName() + ".createMustang()]"
      );
      assertContains(expected.getMessage(),
          ") No implementation for com.google.inject.assistedinject."
            + "FactoryProvider2Test$ProviderBasedColoredCarFactory was bound.");
    }
  }

  interface JavaxProviderBasedColoredCarFactory {
    Car createCar(javax.inject.Provider<Color> colorProvider, javax.inject.Provider<String> stringProvider);
    Mustang createMustang(@Assisted("color") javax.inject.Provider<Color> colorProvider);
  }

  public void testAssistedJavaxProviderIsDisallowed() {
    try {
      Guice.createInjector(new AbstractModule() {
          @Override protected void configure() {
            bind(JavaxProviderBasedColoredCarFactory.class).toProvider(
                FactoryProvider.newFactory(JavaxProviderBasedColoredCarFactory.class, Subaru.class));
          }
      });
      fail();
    } catch (CreationException expected) {
      assertEquals(expected.getMessage(), 4, expected.getErrorMessages().size());
      assertContains(expected.getMessage(),
          ") A Provider may not be a type in a factory method of an AssistedInject."
            + "\n  Offending instance is parameter [1] with key"
            + " [com.google.inject.Provider<" + Color.class.getName() + ">] on method ["
            + JavaxProviderBasedColoredCarFactory.class.getName() + ".createCar()]");
      assertContains(expected.getMessage(),
          ") A Provider may not be a type in a factory method of an AssistedInject."
            + "\n  Offending instance is parameter [2] with key"
            + " [com.google.inject.Provider<java.lang.String>] on method ["
            + JavaxProviderBasedColoredCarFactory.class.getName() + ".createCar()]");
      assertContains(expected.getMessage(),
          ") A Provider may not be a type in a factory method of an AssistedInject."
            + "\n  Offending instance is parameter [1] with key"
            + " [com.google.inject.Provider<" + Color.class.getName() + ">"
            + " annotated with @com.google.inject.assistedinject.Assisted(value=color)]"
            + " on method [" + JavaxProviderBasedColoredCarFactory.class.getName() + ".createMustang()]"
      );
      assertContains(expected.getMessage(),
          ") No implementation for com.google.inject.assistedinject."
            + "FactoryProvider2Test$JavaxProviderBasedColoredCarFactory was bound.");
    }
  }

  public void testFactoryUseBeforeInitialization() {
    ColoredCarFactory carFactory = FactoryProvider.newFactory(ColoredCarFactory.class, Subaru.class)
        .get();
    try {
      carFactory.create(Color.RED);
      fail();
    } catch (IllegalStateException expected) {
      assertContains(expected.getMessage(),
          "Factories.create() factories cannot be used until they're initialized by Guice.");
    }
  }

  interface MustangFactory {
    Mustang create(Color color);
  }

  public void testFactoryBuildingConcreteTypes() {
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        bind(double.class).toInstance(5.0d);
        // note there is no 'thatMakes()' call here:
        bind(MustangFactory.class).toProvider(
            FactoryProvider.newFactory(MustangFactory.class, Mustang.class));
      }
    });
    MustangFactory factory = injector.getInstance(MustangFactory.class);

    Mustang mustang = factory.create(Color.RED);
    assertSame(Color.RED, mustang.color);
    assertEquals(5.0d, mustang.engineSize);
  }

  static class Fleet {
    @Inject Mustang mustang;
    @Inject Camaro camaro;
  }

  interface FleetFactory {
    Fleet createFleet(Color color);
  }

  public void testInjectDeepIntoConstructedObjects() {
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        bind(double.class).toInstance(5.0d);
        bind(int.class).annotatedWith(Names.named("horsePower")).toInstance(250);
        bind(int.class).annotatedWith(Names.named("modelYear")).toInstance(1984);
        bind(FleetFactory.class).toProvider(FactoryProvider.newFactory(FleetFactory.class,
            Fleet.class));
      }
    });

    FleetFactory fleetFactory = injector.getInstance(FleetFactory.class);
    Fleet fleet = fleetFactory.createFleet(Color.RED);

    assertSame(Color.RED, fleet.mustang.color);
    assertEquals(5.0d, fleet.mustang.engineSize);
    assertSame(Color.RED, fleet.camaro.color);
    assertEquals(250, fleet.camaro.horsePower);
    assertEquals(1984, fleet.camaro.modelYear);
  }

  interface TwoToneCarFactory {
    Car create(@Assisted("paint") Color paint, @Assisted("fabric") Color fabric);
  }

  static class Maxima implements Car {
    @Inject @Assisted("paint") Color paint;
    @Inject @Assisted("fabric") Color fabric;
  }

  public void testDistinctKeys() {
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        bind(TwoToneCarFactory.class).toProvider(
            FactoryProvider.newFactory(TwoToneCarFactory.class, Maxima.class));
      }
    });

    TwoToneCarFactory factory = injector.getInstance(TwoToneCarFactory.class);
    Maxima maxima = (Maxima) factory.create(Color.BLACK, Color.GRAY);
    assertSame(Color.BLACK, maxima.paint);
    assertSame(Color.GRAY, maxima.fabric);
  }

  interface DoubleToneCarFactory {
    Car create(@Assisted("paint") Color paint, @Assisted("paint") Color morePaint);
  }

  public void testDuplicateKeys() {
    try {
      Guice.createInjector(new AbstractModule() {
        @Override protected void configure() {
          bind(DoubleToneCarFactory.class).toProvider(
              FactoryProvider.newFactory(DoubleToneCarFactory.class, Maxima.class));
        }
      });
      fail();
    } catch (CreationException expected) {
      assertContains(expected.getMessage(), "A binding to " + Color.class.getName() + " annotated with @"
          + Assisted.class.getName() + "(value=paint) was already configured at");
    }
  }

  /*if[AOP]*/
  public void testMethodInterceptorsOnAssistedTypes() {
    final AtomicInteger invocationCount = new AtomicInteger();
    final org.aopalliance.intercept.MethodInterceptor interceptor
        = new org.aopalliance.intercept.MethodInterceptor() {
      public Object invoke(org.aopalliance.intercept.MethodInvocation methodInvocation)
          throws Throwable {
        invocationCount.incrementAndGet();
        return methodInvocation.proceed();
      }
    };

    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        bindInterceptor(Matchers.any(), Matchers.any(), interceptor);
        bind(Double.class).toInstance(5.0d);
        bind(ColoredCarFactory.class).toProvider(
            FactoryProvider.newFactory(ColoredCarFactory.class, Mustang.class));
      }
    });

    ColoredCarFactory factory = injector.getInstance(ColoredCarFactory.class);
    Mustang mustang = (Mustang) factory.create(Color.GREEN);
    assertEquals(0, invocationCount.get());
    mustang.drive();
    assertEquals(1, invocationCount.get());
  }
  /*end[AOP]*/

  /**
   * Our factories aren't reusable across injectors. Although this behaviour isn't something we
   * like, I have a test case to make sure the error message is pretty.
   */
  public void testFactoryReuseErrorMessageIsPretty() {
    final Provider<ColoredCarFactory> factoryProvider
        = FactoryProvider.newFactory(ColoredCarFactory.class, Mustang.class);

    Guice.createInjector(new AbstractModule() {
      @Override protected void configure() {
        bind(Double.class).toInstance(5.0d);
        bind(ColoredCarFactory.class).toProvider(factoryProvider);
      }
    });

    try {
      Guice.createInjector(new AbstractModule() {
        @Override protected void configure() {
          bind(Double.class).toInstance(5.0d);
          bind(ColoredCarFactory.class).toProvider(factoryProvider);
        }
      });
      fail();
    } catch(CreationException expected) {
      assertContains(expected.getMessage(),
          "Factories.create() factories may only be used in one Injector!");
    }
  }

  public void testNonAssistedFactoryMethodParameter() {
    try {
      FactoryProvider.newFactory(NamedParameterFactory.class, Mustang.class);
      fail();
    } catch(ConfigurationException expected) {
      assertContains(expected.getMessage(),
          "Only @Assisted is allowed for factory parameters, but found @" + Named.class.getName());
    }
  }

  interface NamedParameterFactory {
    Car create(@Named("seats") int seats, double engineSize);
  }


  public void testDefaultAssistedAnnotation() throws NoSuchFieldException {
    Assisted plainAssisted
        = Subaru.class.getDeclaredField("colorProvider").getAnnotation(Assisted.class);
    assertEqualsBothWays(FactoryProvider2.DEFAULT_ANNOTATION, plainAssisted);
    assertEquals(FactoryProvider2.DEFAULT_ANNOTATION.toString(), plainAssisted.toString());
  }

  interface GenericColoredCarFactory<T extends Car> {
    T create(Color color);
  }

  public void testGenericAssistedFactory() {
    final TypeLiteral<GenericColoredCarFactory<Mustang>> mustangTypeLiteral
        = new TypeLiteral<GenericColoredCarFactory<Mustang>>() {};
    final TypeLiteral<GenericColoredCarFactory<Camaro>> camaroTypeLiteral
        = new TypeLiteral<GenericColoredCarFactory<Camaro>>() {};

    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        bind(Double.class).toInstance(5.0d);
        bind(int.class).annotatedWith(Names.named("horsePower")).toInstance(250);
        bind(int.class).annotatedWith(Names.named("modelYear")).toInstance(1984);
        bind(mustangTypeLiteral)
            .toProvider(FactoryProvider.newFactory(mustangTypeLiteral, TypeLiteral.get(Mustang.class)));
        bind(camaroTypeLiteral)
            .toProvider(FactoryProvider.newFactory(camaroTypeLiteral, TypeLiteral.get(Camaro.class)));
      }
    });

    GenericColoredCarFactory<Mustang> mustangFactory
        = injector.getInstance(Key.get(mustangTypeLiteral));
    GenericColoredCarFactory<Camaro> camaroFactory
        = injector.getInstance(Key.get(camaroTypeLiteral));

    Mustang blueMustang = mustangFactory.create(Color.BLUE);
    assertEquals(Color.BLUE, blueMustang.color);
    assertEquals(5.0d, blueMustang.engineSize);

    Camaro redCamaro = camaroFactory.create(Color.RED);
    assertEquals(Color.RED, redCamaro.color);
    assertEquals(1984, redCamaro.modelYear);
    assertEquals(250, redCamaro.horsePower);
  }

  @SuppressWarnings("unused")
  public interface Insurance<T extends Car> {
  }

  public static class MustangInsurance implements Insurance<Mustang> {
    private final double premium;
    private final double limit;
    @SuppressWarnings("unused") private Mustang car;

    @Inject
    public MustangInsurance(@Named("lowLimit") double limit, @Assisted Mustang car,
        @Assisted double premium) {
      this.premium = premium;
      this.limit = limit;
      this.car = car;
    }

    public void sell() {}
  }

  public static class CamaroInsurance implements Insurance<Camaro> {
    private final double premium;
    private final double limit;
    @SuppressWarnings("unused") private Camaro car;

    @Inject
    public CamaroInsurance(@Named("highLimit") double limit, @Assisted Camaro car,
        @Assisted double premium) {
      this.premium = premium;
      this.limit = limit;
      this.car = car;
    }

    public void sell() {}
  }

  public interface MustangInsuranceFactory {
    public Insurance<Mustang> create(Mustang car, double premium);
  }

  public interface CamaroInsuranceFactory {
    public Insurance<Camaro> create(Camaro car, double premium);
  }

  public void testAssistedFactoryForConcreteType() {

    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        bind(Double.class).annotatedWith(Names.named("lowLimit")).toInstance(50000.0d);
        bind(Double.class).annotatedWith(Names.named("highLimit")).toInstance(100000.0d);
        bind(MustangInsuranceFactory.class).toProvider(
            FactoryProvider.newFactory(MustangInsuranceFactory.class, MustangInsurance.class));
        bind(CamaroInsuranceFactory.class).toProvider(
            FactoryProvider.newFactory(CamaroInsuranceFactory.class, CamaroInsurance.class));
      }
    });

    MustangInsuranceFactory mustangInsuranceFactory =
        injector.getInstance(MustangInsuranceFactory.class);
    CamaroInsuranceFactory camaroInsuranceFactory =
        injector.getInstance(CamaroInsuranceFactory.class);

    Mustang mustang = new Mustang(5000d, Color.BLACK);
    MustangInsurance mustangPolicy =
        (MustangInsurance) mustangInsuranceFactory.create(mustang, 800.0d);
    assertEquals(800.0d, mustangPolicy.premium);
    assertEquals(50000.0d, mustangPolicy.limit);

    Camaro camaro = new Camaro(3000, 1967, Color.BLUE);
    CamaroInsurance camaroPolicy = (CamaroInsurance) camaroInsuranceFactory.create(camaro, 800.0d);
    assertEquals(800.0d, camaroPolicy.premium);
    assertEquals(100000.0d, camaroPolicy.limit);
  }

  public interface InsuranceFactory<T extends Car> {
    public Insurance<T> create(T car, double premium);
  }

  public void testAssistedFactoryForParameterizedType() {
    final TypeLiteral<InsuranceFactory<Mustang>> mustangInsuranceFactoryType =
        new TypeLiteral<InsuranceFactory<Mustang>>() {};
    final TypeLiteral<InsuranceFactory<Camaro>> camaroInsuranceFactoryType =
        new TypeLiteral<InsuranceFactory<Camaro>>() {};

    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        bind(Double.class).annotatedWith(Names.named("lowLimit")).toInstance(50000.0d);
        bind(Double.class).annotatedWith(Names.named("highLimit")).toInstance(100000.0d);
        bind(mustangInsuranceFactoryType).toProvider(FactoryProvider.newFactory(
            mustangInsuranceFactoryType, TypeLiteral.get(MustangInsurance.class)));
        bind(camaroInsuranceFactoryType).toProvider(FactoryProvider.newFactory(
            camaroInsuranceFactoryType, TypeLiteral.get(CamaroInsurance.class)));
      }
    });

    InsuranceFactory<Mustang> mustangInsuranceFactory =
        injector.getInstance(Key.get(mustangInsuranceFactoryType));
    InsuranceFactory<Camaro> camaroInsuranceFactory =
        injector.getInstance(Key.get(camaroInsuranceFactoryType));

    Mustang mustang = new Mustang(5000d, Color.BLACK);
    MustangInsurance mustangPolicy =
        (MustangInsurance) mustangInsuranceFactory.create(mustang, 800.0d);
    assertEquals(800.0d, mustangPolicy.premium);
    assertEquals(50000.0d, mustangPolicy.limit);

    Camaro camaro = new Camaro(3000, 1967, Color.BLUE);
    CamaroInsurance camaroPolicy = (CamaroInsurance) camaroInsuranceFactory.create(camaro, 800.0d);
    assertEquals(800.0d, camaroPolicy.premium);
    assertEquals(100000.0d, camaroPolicy.limit);
  }

  public static class AutoInsurance<T extends Car> implements Insurance<T> {
    private final double premium;
    private final double limit;
    private final T car;

    @Inject
    public AutoInsurance(double limit, @Assisted T car, @Assisted double premium) {
      this.limit = limit;
      this.car = car;
      this.premium = premium;
    }

    public void sell() {}
  }

  public void testAssistedFactoryForTypeVariableParameters() {
    final TypeLiteral<InsuranceFactory<Camaro>> camaroInsuranceFactoryType =
        new TypeLiteral<InsuranceFactory<Camaro>>() {};

    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        bind(Double.class).toInstance(50000.0d);
        bind(camaroInsuranceFactoryType).toProvider(FactoryProvider.newFactory(
            camaroInsuranceFactoryType, new TypeLiteral<AutoInsurance<Camaro>>() {}));
      }
    });

    InsuranceFactory<Camaro> camaroInsuranceFactory =
        injector.getInstance(Key.get(camaroInsuranceFactoryType));

    Camaro camaro = new Camaro(3000, 1967, Color.BLUE);
    AutoInsurance<?> camaroPolicy =
        (AutoInsurance<?>) camaroInsuranceFactory.create(camaro, 800.0d);
    assertEquals(800.0d, camaroPolicy.premium);
    assertEquals(50000.0d, camaroPolicy.limit);
    assertEquals(camaro, camaroPolicy.car);
  }

  public void testInjectingAndUsingInjector() {
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override protected void configure() {
        bind(ColoredCarFactory.class).toProvider(
            FactoryProvider.newFactory(ColoredCarFactory.class, Segway.class));
      }
    });

    ColoredCarFactory carFactory = injector.getInstance(ColoredCarFactory.class);
    Segway green = (Segway)carFactory.create(Color.GREEN);
    assertSame(Color.GREEN, green.getColor());
    assertSame(Color.GREEN, green.getColor());
    
    Segway pink = (Segway)carFactory.create(Color.PINK);
    assertSame(Color.PINK, pink.getColor());
    assertSame(Color.PINK, pink.getColor());
    assertSame(Color.GREEN, green.getColor());
  }
  
  public void testDuplicateAssistedFactoryBinding() {
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        bind(Double.class).toInstance(5.0d);
        bind(ColoredCarFactory.class).toProvider(
            FactoryProvider.newFactory(ColoredCarFactory.class, Mustang.class));
        bind(ColoredCarFactory.class).toProvider(
            FactoryProvider.newFactory(ColoredCarFactory.class, Mustang.class));
      }
    });
    ColoredCarFactory carFactory = injector.getInstance(ColoredCarFactory.class);

    Mustang blueMustang = (Mustang) carFactory.create(Color.BLUE);
    assertEquals(Color.BLUE, blueMustang.color);
    assertEquals(5.0d, blueMustang.engineSize);

    Mustang redMustang = (Mustang) carFactory.create(Color.RED);
    assertEquals(Color.RED, redMustang.color);
    assertEquals(5.0d, redMustang.engineSize);
  }

  public interface Equals {

    enum ComparisonMethod { SHALLOW, DEEP; }

    interface Factory {
      Equals equals(Equals.ComparisonMethod comparisonMethod);
    }

    public static class Impl implements Equals {
      private final double sigma;
      private final ComparisonMethod comparisonMethod;

      @AssistedInject
      public Impl(double sigma, @Assisted ComparisonMethod comparisonMethod) {
        this.sigma = sigma;
        this.comparisonMethod = comparisonMethod;
      }
    }
  }

  public void testFactoryMethodCalledEquals() {
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      protected void configure() {
        bind(Double.class).toInstance(0.01d);
        bind(Equals.Factory.class).toProvider(
            FactoryProvider.newFactory(Equals.Factory.class, Equals.Impl.class));
      }
    });
    Equals.Factory equalsFactory = injector.getInstance(Equals.Factory.class);
    Equals.Impl shallowEquals = (Impl) equalsFactory.equals(ComparisonMethod.SHALLOW);
    assertEquals(ComparisonMethod.SHALLOW, shallowEquals.comparisonMethod);
    assertEquals(0.01d, shallowEquals.sigma);
  }

  static class Segway implements Car {
    @Inject Injector injector;

    Color getColor() { return injector.getInstance(Key.get(Color.class, FactoryProvider2.DEFAULT_ANNOTATION)); }
  }

  public void testReturnValueMatchesParamValue() {
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override
      public void configure() {
        install(new FactoryModuleBuilder().build(Delegater.Factory.class));
      }
    });
    Delegater delegate = new Delegater();
    Delegater user = injector.getInstance(Delegater.Factory.class).create(delegate);
    assertSame(delegate, user.delegate);
  }

  static class Delegater {
    interface Factory {
      Delegater create(Delegater delegate);
    }

    private final Delegater delegate;

    @Inject Delegater(@Assisted Delegater delegater) {
      this.delegate = delegater;
    }

    Delegater() {
      this.delegate = null;
    }
  }

  public static abstract class AbstractAssisted {
    interface Factory<O extends AbstractAssisted, I extends CharSequence> {
      O create(I string);
    }
  }

  static class ConcreteAssisted extends AbstractAssisted {
    @Inject ConcreteAssisted(@SuppressWarnings("unused") @Assisted String string) {}
  }

  static class ConcreteAssistedWithOverride extends AbstractAssisted {
    @AssistedInject
    ConcreteAssistedWithOverride(@SuppressWarnings("unused") @Assisted String string) {}

    @AssistedInject
    ConcreteAssistedWithOverride(@SuppressWarnings("unused") @Assisted StringBuilder sb) {}

    interface Factory extends AbstractAssisted.Factory<ConcreteAssistedWithOverride, String> {
      @Override ConcreteAssistedWithOverride create(String string);
    }

    interface Factory2 extends AbstractAssisted.Factory<ConcreteAssistedWithOverride, String> {
      @Override ConcreteAssistedWithOverride create(String string);
      ConcreteAssistedWithOverride create(StringBuilder sb);
    }
  }

  static class ConcreteAssistedWithoutOverride extends AbstractAssisted {
    @Inject ConcreteAssistedWithoutOverride(@SuppressWarnings("unused") @Assisted String string) {}
    interface Factory extends AbstractAssisted.Factory<ConcreteAssistedWithoutOverride, String> {}
  }

  public static class Public extends AbstractAssisted {
    @AssistedInject Public(@SuppressWarnings("unused") @Assisted String string) {}
    @AssistedInject Public(@SuppressWarnings("unused") @Assisted StringBuilder sb) {}

    public interface Factory extends AbstractAssisted.Factory<Public, String> {
      @Override Public create(String string);
      Public create(StringBuilder sb);
    }
  }

  // See https://github.com/google/guice/issues/904
  public void testGeneratedDefaultMethodsForwardCorrectly() {
    final Key<AbstractAssisted.Factory<ConcreteAssisted, String>> concreteKey =
        new Key<AbstractAssisted.Factory<ConcreteAssisted, String>>() {};
    Injector injector = Guice.createInjector(new AbstractModule() {
      @Override protected void configure() {
        install(new FactoryModuleBuilder().build(ConcreteAssistedWithOverride.Factory.class));
        install(new FactoryModuleBuilder().build(ConcreteAssistedWithOverride.Factory2.class));
        install(new FactoryModuleBuilder().build(ConcreteAssistedWithoutOverride.Factory.class));
        install(new FactoryModuleBuilder().build(Public.Factory.class));
        install(new FactoryModuleBuilder().build(concreteKey));
      }
    });

    ConcreteAssistedWithOverride.Factory factory1 =
        injector.getInstance(ConcreteAssistedWithOverride.Factory.class);
    factory1.create("foo");
    AbstractAssisted.Factory<ConcreteAssistedWithOverride, String> factory1Abstract = factory1;
    factory1Abstract.create("foo");

    ConcreteAssistedWithOverride.Factory2 factory2 =
        injector.getInstance(ConcreteAssistedWithOverride.Factory2.class);
    factory2.create("foo");
    factory2.create(new StringBuilder("foo"));
    AbstractAssisted.Factory<ConcreteAssistedWithOverride, String> factory2Abstract = factory2;
    factory2Abstract.create("foo");

    ConcreteAssistedWithoutOverride.Factory factory3 =
        injector.getInstance(ConcreteAssistedWithoutOverride.Factory.class);
    factory3.create("foo");
    AbstractAssisted.Factory<ConcreteAssistedWithoutOverride, String> factory3Abstract = factory3;
    factory3Abstract.create("foo");

    Public.Factory factory4 = injector.getInstance(Public.Factory.class);
    factory4.create("foo");
    factory4.create(new StringBuilder("foo"));
    AbstractAssisted.Factory<Public, String> factory4Abstract = factory4;
    factory4Abstract.create("foo");

    AbstractAssisted.Factory<ConcreteAssisted, String> factory5 =
        injector.getInstance(concreteKey);
    factory5.create("foo");
  }
}
