/**
 * 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.multibindings;

import static com.google.common.base.Predicates.equalTo;
import static com.google.common.collect.Iterables.filter;
import static com.google.common.collect.Iterables.getOnlyElement;
import static com.google.inject.multibindings.Element.Type.MULTIBINDER;
import static com.google.inject.name.Names.named;

import com.google.common.base.Objects;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.inject.AbstractModule;
import com.google.inject.Binder;
import com.google.inject.Binding;
import com.google.inject.ConfigurationException;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.Module;
import com.google.inject.TypeLiteral;
import com.google.inject.binder.LinkedBindingBuilder;
import com.google.inject.internal.Annotations;
import com.google.inject.internal.Errors;
import com.google.inject.spi.BindingTargetVisitor;
import com.google.inject.spi.Dependency;
import com.google.inject.spi.HasDependencies;
import com.google.inject.spi.Message;
import com.google.inject.spi.ProviderInstanceBinding;
import com.google.inject.spi.ProviderWithExtensionVisitor;
import com.google.inject.spi.Toolable;
import com.google.inject.util.Types;

import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * An API to bind multiple values separately, only to later inject them as a
 * complete collection. Multibinder is intended for use in your application's
 * module:
 * <pre><code>
 * public class SnacksModule extends AbstractModule {
 *   protected void configure() {
 *     Multibinder&lt;Snack&gt; multibinder
 *         = Multibinder.newSetBinder(binder(), Snack.class);
 *     multibinder.addBinding().toInstance(new Twix());
 *     multibinder.addBinding().toProvider(SnickersProvider.class);
 *     multibinder.addBinding().to(Skittles.class);
 *   }
 * }</code></pre>
 *
 * <p>With this binding, a {@link Set}{@code <Snack>} can now be injected:
 * <pre><code>
 * class SnackMachine {
 *   {@literal @}Inject
 *   public SnackMachine(Set&lt;Snack&gt; snacks) { ... }
 * }</code></pre>
 *
 * <p>Contributing multibindings from different modules is supported. For
 * example, it is okay for both {@code CandyModule} and {@code ChipsModule}
 * to create their own {@code Multibinder<Snack>}, and to each contribute
 * bindings to the set of snacks. When that set is injected, it will contain
 * elements from both modules.
 *
 * <p>The set's iteration order is consistent with the binding order. This is
 * convenient when multiple elements are contributed by the same module because
 * that module can order its bindings appropriately. Avoid relying on the
 * iteration order of elements contributed by different modules, since there is
 * no equivalent mechanism to order modules.
 *
 * <p>The set is unmodifiable.  Elements can only be added to the set by
 * configuring the multibinder.  Elements can never be removed from the set.
 *
 * <p>Elements are resolved at set injection time. If an element is bound to a
 * provider, that provider's get method will be called each time the set is
 * injected (unless the binding is also scoped).
 *
 * <p>Annotations are be used to create different sets of the same element
 * type. Each distinct annotation gets its own independent collection of
 * elements.
 *
 * <p><strong>Elements must be distinct.</strong> If multiple bound elements
 * have the same value, set injection will fail.
 *
 * <p><strong>Elements must be non-null.</strong> If any set element is null,
 * set injection will fail.
 *
 * @author jessewilson@google.com (Jesse Wilson)
 */
public abstract class Multibinder<T> {
  private Multibinder() {}

  /**
   * Returns a new multibinder that collects instances of {@code type} in a {@link Set} that is
   * itself bound with no binding annotation.
   */
  public static <T> Multibinder<T> newSetBinder(Binder binder, TypeLiteral<T> type) {
    binder = binder.skipSources(RealMultibinder.class, Multibinder.class);
    RealMultibinder<T> result = new RealMultibinder<T>(binder, type,
        Key.get(Multibinder.<T>setOf(type)));
    binder.install(result);
    return result;
  }

  /**
   * Returns a new multibinder that collects instances of {@code type} in a {@link Set} that is
   * itself bound with no binding annotation.
   */
  public static <T> Multibinder<T> newSetBinder(Binder binder, Class<T> type) {
    return newSetBinder(binder, TypeLiteral.get(type));
  }

  /**
   * Returns a new multibinder that collects instances of {@code type} in a {@link Set} that is
   * itself bound with {@code annotation}.
   */
  public static <T> Multibinder<T> newSetBinder(
      Binder binder, TypeLiteral<T> type, Annotation annotation) {
    binder = binder.skipSources(RealMultibinder.class, Multibinder.class);
    RealMultibinder<T> result = new RealMultibinder<T>(binder, type,
        Key.get(Multibinder.<T>setOf(type), annotation));
    binder.install(result);
    return result;
  }

  /**
   * Returns a new multibinder that collects instances of {@code type} in a {@link Set} that is
   * itself bound with {@code annotation}.
   */
  public static <T> Multibinder<T> newSetBinder(
      Binder binder, Class<T> type, Annotation annotation) {
    return newSetBinder(binder, TypeLiteral.get(type), annotation);
  }

  /**
   * Returns a new multibinder that collects instances of {@code type} in a {@link Set} that is
   * itself bound with {@code annotationType}.
   */
  public static <T> Multibinder<T> newSetBinder(Binder binder, TypeLiteral<T> type,
      Class<? extends Annotation> annotationType) {
    binder = binder.skipSources(RealMultibinder.class, Multibinder.class);
    RealMultibinder<T> result = new RealMultibinder<T>(binder, type,
        Key.get(Multibinder.<T>setOf(type), annotationType));
    binder.install(result);
    return result;
  }

  /**
   * Returns a new multibinder that collects instances of {@code type} in a {@link Set} that is
   * itself bound with {@code annotationType}.
   */
  public static <T> Multibinder<T> newSetBinder(Binder binder, Class<T> type,
      Class<? extends Annotation> annotationType) {
    return newSetBinder(binder, TypeLiteral.get(type), annotationType);
  }

  @SuppressWarnings("unchecked") // wrapping a T in a Set safely returns a Set<T>
  static <T> TypeLiteral<Set<T>> setOf(TypeLiteral<T> elementType) {
    Type type = Types.setOf(elementType.getType());
    return (TypeLiteral<Set<T>>) TypeLiteral.get(type);
  }

  /**
   * Configures the bound set to silently discard duplicate elements. When multiple equal values are
   * bound, the one that gets included is arbitrary. When multiple modules contribute elements to
   * the set, this configuration option impacts all of them.
   *
   * @return this multibinder
   * @since 3.0
   */
  public abstract Multibinder<T> permitDuplicates();

  /**
   * Returns a binding builder used to add a new element in the set. Each
   * bound element must have a distinct value. Bound providers will be
   * evaluated each time the set is injected.
   *
   * <p>It is an error to call this method without also calling one of the
   * {@code to} methods on the returned binding builder.
   *
   * <p>Scoping elements independently is supported. Use the {@code in} method
   * to specify a binding scope.
   */
  public abstract LinkedBindingBuilder<T> addBinding();

  /**
   * The actual multibinder plays several roles:
   *
   * <p>As a Multibinder, it acts as a factory for LinkedBindingBuilders for
   * each of the set's elements. Each binding is given an annotation that
   * identifies it as a part of this set.
   *
   * <p>As a Module, it installs the binding to the set itself. As a module,
   * this implements equals() and hashcode() in order to trick Guice into
   * executing its configure() method only once. That makes it so that
   * multiple multibinders can be created for the same target collection, but
   * only one is bound. Since the list of bindings is retrieved from the
   * injector itself (and not the multibinder), each multibinder has access to
   * all contributions from all multibinders.
   *
   * <p>As a Provider, this constructs the set instances.
   *
   * <p>We use a subclass to hide 'implements Module, Provider' from the public
   * API.
   */
  static final class RealMultibinder<T> extends Multibinder<T>
      implements Module, ProviderWithExtensionVisitor<Set<T>>, HasDependencies,
          MultibinderBinding<Set<T>> {

    private final TypeLiteral<T> elementType;
    private final String setName;
    private final Key<Set<T>> setKey;
    private final Key<Boolean> permitDuplicatesKey;

    /* the target injector's binder. non-null until initialization, null afterwards */
    private Binder binder;

    /* a binding for each element in the set. null until initialization, non-null afterwards */
    private ImmutableList<Binding<T>> bindings;
    private Set<Dependency<?>> dependencies;

    /** whether duplicates are allowed. Possibly configured by a different instance */
    private boolean permitDuplicates;

    private RealMultibinder(Binder binder, TypeLiteral<T> elementType, Key<Set<T>> setKey) {
      this.binder = checkNotNull(binder, "binder");
      this.elementType = checkNotNull(elementType, "elementType");
      this.setKey = checkNotNull(setKey, "setKey");
      this.setName = nameOf(setKey);
      this.permitDuplicatesKey = Key.get(Boolean.class, named(toString() + " permits duplicates"));
    }

    /**
     * Returns the name the set should use.  This is based on the annotation.
     * If the annotation has an instance and is not a marker annotation,
     * we ask the annotation for its toString.  If it was a marker annotation
     * or just an annotation type, we use the annotation's name. Otherwise,
     * the name is the empty string.
     */
    private static String nameOf(Key<?> setKey) {
      Annotation annotation = setKey.getAnnotation();
      Class<? extends Annotation> annotationType = setKey.getAnnotationType();
      if (annotation != null && !Annotations.isMarker(annotationType)) {
        return setKey.getAnnotation().toString();
      } else if (setKey.getAnnotationType() != null) {
        return "@" + setKey.getAnnotationType().getName();
      } else {
        return "";
      }
    }

    public void configure(Binder binder) {
      checkConfiguration(!isInitialized(), "Multibinder was already initialized");

      binder.bind(setKey).toProvider(this);
    }

    @Override
    public Multibinder<T> permitDuplicates() {
      binder.install(new PermitDuplicatesModule(permitDuplicatesKey));
      return this;
    }

    @Override public LinkedBindingBuilder<T> addBinding() {
      checkConfiguration(!isInitialized(), "Multibinder was already initialized");

      return RealElement.addBinding(binder, MULTIBINDER, elementType, setName);
    }

    /**
     * Invoked by Guice at Injector-creation time to prepare providers for each
     * element in this set. At this time the set's size is known, but its
     * contents are only evaluated when get() is invoked.
     */
    @Toolable @Inject void initialize(Injector injector) {
      List<Binding<T>> bindings = Lists.newArrayList();
      List<Dependency<?>> dependencies = Lists.newArrayList();
      for (Binding<?> entry : injector.findBindingsByType(elementType)) {
        if (keyMatches(entry.getKey())) {
          @SuppressWarnings("unchecked") // protected by findBindingsByType()
          Binding<T> binding = (Binding<T>) entry;
          bindings.add(binding);
          dependencies.add(Dependency.get(binding.getKey()));
        }
      }

      this.bindings = ImmutableList.copyOf(bindings);
      this.dependencies = ImmutableSet.copyOf(dependencies);
      this.permitDuplicates = permitsDuplicates(injector);
      this.binder = null;
    }

    boolean permitsDuplicates(Injector injector) {
      return injector.getBindings().containsKey(permitDuplicatesKey);
    }

    private boolean keyMatches(Key<?> key) {
      return key.getTypeLiteral().equals(elementType)
          && key.getAnnotation() instanceof Element
          && ((Element) key.getAnnotation()).setName().equals(setName)
          && ((Element) key.getAnnotation()).type() == MULTIBINDER;
    }

    private boolean isInitialized() {
      return binder == null;
    }

    public Set<T> get() {
      checkConfiguration(isInitialized(), "Multibinder is not initialized");

      Map<T, Binding<T>> result = new LinkedHashMap<T, Binding<T>>();
      for (Binding<T> binding : bindings) {
        final T newValue = binding.getProvider().get();
        checkConfiguration(newValue != null, "Set injection failed due to null element");
        Binding<T> duplicateBinding = result.put(newValue, binding);
        if (!permitDuplicates && duplicateBinding != null) {
          throw newDuplicateValuesException(result, binding, newValue, duplicateBinding);
        }
      }
      return ImmutableSet.copyOf(result.keySet());
    }

    @SuppressWarnings("unchecked")
    public <B, V> V acceptExtensionVisitor(
        BindingTargetVisitor<B, V> visitor,
        ProviderInstanceBinding<? extends B> binding) {
      if (visitor instanceof MultibindingsTargetVisitor) {
        return ((MultibindingsTargetVisitor<Set<T>, V>) visitor).visit(this);
      } else {
        return visitor.visit(binding);
      }
    }

    String getSetName() {
      return setName;
    }

    public TypeLiteral<?> getElementTypeLiteral() {
      return elementType;
    }

    public Key<Set<T>> getSetKey() {
      return setKey;
    }

    @SuppressWarnings("unchecked")
    public List<Binding<?>> getElements() {
      if (isInitialized()) {
        return (List<Binding<?>>) (List<?>) bindings; // safe because bindings is immutable.
      } else {
        throw new UnsupportedOperationException("getElements() not supported for module bindings");
      }
    }

    public boolean permitsDuplicates() {
      if (isInitialized()) {
        return permitDuplicates;
      } else {
        throw new UnsupportedOperationException(
            "permitsDuplicates() not supported for module bindings");
      }
    }

    public boolean containsElement(com.google.inject.spi.Element element) {
      if (element instanceof Binding) {
        Binding<?> binding = (Binding<?>) element;
        return keyMatches(binding.getKey())
            || binding.getKey().equals(permitDuplicatesKey)
            || binding.getKey().equals(setKey);
      } else {
        return false;
      }
    }

    public Set<Dependency<?>> getDependencies() {
      if (!isInitialized()) {
        return ImmutableSet.<Dependency<?>>of(Dependency.get(Key.get(Injector.class)));
      } else {
        return dependencies;
      }
    }

    @Override public boolean equals(Object o) {
      return o instanceof RealMultibinder
          && ((RealMultibinder<?>) o).setKey.equals(setKey);
    }

    @Override public int hashCode() {
      return setKey.hashCode();
    }

    @Override public String toString() {
      return new StringBuilder()
          .append(setName)
          .append(setName.length() > 0 ? " " : "")
          .append("Multibinder<")
          .append(elementType)
          .append(">")
          .toString();
    }
  }

  /**
   * We install the permit duplicates configuration as its own binding, all by itself. This way,
   * if only one of a multibinder's users remember to call permitDuplicates(), they're still
   * permitted.
   */
  private static class PermitDuplicatesModule extends AbstractModule {
    private final Key<Boolean> key;

    PermitDuplicatesModule(Key<Boolean> key) {
      this.key = key;
    }

    @Override
    protected void configure() {
      bind(key).toInstance(true);
    }

    @Override public boolean equals(Object o) {
      return o instanceof PermitDuplicatesModule
          && ((PermitDuplicatesModule) o).key.equals(key);
    }

    @Override public int hashCode() {
      return getClass().hashCode() ^ key.hashCode();
    }
  }

  static void checkConfiguration(boolean condition, String format, Object... args) {
    if (condition) {
      return;
    }

    throw new ConfigurationException(ImmutableSet.of(new Message(Errors.format(format, args))));
  }

  private static <T> ConfigurationException newDuplicateValuesException(
      Map<T, Binding<T>> existingBindings,
      Binding<T> binding,
      final T newValue,
      Binding<T> duplicateBinding) {
    T oldValue = getOnlyElement(filter(existingBindings.keySet(), equalTo(newValue)));
    String oldString = oldValue.toString();
    String newString = newValue.toString();
    if (Objects.equal(oldString, newString)) {
      // When the value strings match, just show the source of the bindings
      return new ConfigurationException(ImmutableSet.of(new Message(Errors.format(
          "Set injection failed due to duplicated element \"%s\""
              + "\n    Bound at %s\n    Bound at %s",
          newValue,
          duplicateBinding.getSource(),
          binding.getSource()))));
    } else {
      // When the value strings don't match, include them both as they may be useful for debugging
      return new ConfigurationException(ImmutableSet.of(new Message(Errors.format(
          "Set injection failed due to multiple elements comparing equal:"
              + "\n    \"%s\"\n        bound at %s"
              + "\n    \"%s\"\n        bound at %s",
          oldValue,
          duplicateBinding.getSource(),
          newValue,
          binding.getSource()))));
    }
  }

  static <T> T checkNotNull(T reference, String name) {
    if (reference != null) {
      return reference;
    }

    NullPointerException npe = new NullPointerException(name);
    throw new ConfigurationException(ImmutableSet.of(
        new Message(npe.toString(), npe)));
  }
}
