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

import static com.google.common.base.Preconditions.checkArgument;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.inject.Guice;
import com.google.inject.Key;
import com.google.inject.MembersInjector;
import com.google.inject.Provides;
import com.google.inject.ProvisionException;
import com.google.inject.TypeLiteral;
import com.google.inject.internal.util.SourceProvider;
import com.google.inject.internal.util.StackTraceElements;
import com.google.inject.spi.Dependency;
import com.google.inject.spi.InjectionListener;
import com.google.inject.spi.Message;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * A checked exception for provisioning errors.
 *
 * <p>This is the internal dual of {@link ProvisionException}, similar to the relationship between
 * {@link com.google.inject.ConfigurationException} and {@link ErrorsException}. This is useful for
 * several reasons:
 *
 * <ul>
 *   <li>Since it is a checked exception, we get some assistance from the java compiler in ensuring
 *       that we correctly handle it everywhere. ProvisionException is unchecked.
 *   <li>Since this is an internal package, we can add useful construction and mutation APIs that
 *       would be undesirable in a public supported API.
 * </ul>
 *
 * <p>This exception will be thrown when errors are encountered during provisioning, ErrorsException
 * will continue to be used for errors that are encountered during provisioning and both make use of
 * the {@link Message} as the core model.
 *
 * <p>NOTE: this object stores a list of messages but in the most common case the cardinality will
 * be 1. The only time that multiple errors might be reported via this mechanism is when {@link
 * #errorInUserCode} is called with an exception that holds multiple errors (like
 * ProvisionException).
 */
public final class InternalProvisionException extends Exception {
  private static final Logger logger = Logger.getLogger(Guice.class.getName());
  private static final Set<Dependency<?>> warnedDependencies =
      Collections.newSetFromMap(new ConcurrentHashMap<Dependency<?>, Boolean>());


  public static InternalProvisionException circularDependenciesDisabled(Class<?> expectedType) {
    return create(
        "Found a circular dependency involving %s, and circular dependencies are disabled.",
        expectedType);
  }

  public static InternalProvisionException cannotProxyClass(Class<?> expectedType) {
    return create(
        "Tried proxying %s to support a circular dependency, but it is not an interface.",
        expectedType);
  }

  public static InternalProvisionException create(String format, Object... arguments) {
    return new InternalProvisionException(Messages.create(format, arguments));
  }

  public static InternalProvisionException errorInUserCode(
      Throwable cause, String messageFormat, Object... arguments) {
    Collection<Message> messages = Errors.getMessagesFromThrowable(cause);
    if (!messages.isEmpty()) {
      // TODO(lukes): it seems like we are dropping some valuable context here..
      // consider eliminating this special case
      return new InternalProvisionException(messages);
    } else {
      return new InternalProvisionException(Messages.create(cause, messageFormat, arguments));
    }
  }

  public static InternalProvisionException subtypeNotProvided(
      Class<? extends javax.inject.Provider<?>> providerType, Class<?> type) {
    return create("%s doesn't provide instances of %s.", providerType, type);
  }

  public static InternalProvisionException errorInProvider(Throwable cause) {
    return errorInUserCode(cause, "Error in custom provider, %s", cause);
  }

  public static InternalProvisionException errorInjectingMethod(Throwable cause) {
    return errorInUserCode(cause, "Error injecting method, %s", cause);
  }

  public static InternalProvisionException errorInjectingConstructor(Throwable cause) {
    return errorInUserCode(cause, "Error injecting constructor, %s", cause);
  }

  public static InternalProvisionException errorInUserInjector(
      MembersInjector<?> listener, TypeLiteral<?> type, RuntimeException cause) {
    return errorInUserCode(
        cause, "Error injecting %s using %s.%n Reason: %s", type, listener, cause);
  }

  public static InternalProvisionException jitDisabled(Key<?> key) {
    return create("Explicit bindings are required and %s is not explicitly bound.", key);
  }

  public static InternalProvisionException errorNotifyingInjectionListener(
      InjectionListener<?> listener, TypeLiteral<?> type, RuntimeException cause) {
    return errorInUserCode(
        cause, "Error notifying InjectionListener %s of %s.%n Reason: %s", listener, type, cause);
  }

  /**
   * Returns {@code value} if it is non-null or allowed to be null. Otherwise a message is added and
   * an {@code InternalProvisionException} is thrown.
   */
  static void onNullInjectedIntoNonNullableDependency(Object source, Dependency<?> dependency)
      throws InternalProvisionException {
    // Hack to allow null parameters to @Provides methods, for backwards compatibility.
    if (dependency.getInjectionPoint().getMember() instanceof Method) {
      Method annotated = (Method) dependency.getInjectionPoint().getMember();
      if (annotated.isAnnotationPresent(Provides.class)) {
        switch (InternalFlags.getNullableProvidesOption()) {
          case ERROR:
            break; // break out & let the below exception happen
          case IGNORE:
            return; // user doesn't care about injecting nulls to non-@Nullables.
          case WARN:
            // Warn only once, otherwise we spam logs too much.
            if (warnedDependencies.add(dependency)) {
              logger.log(
                  Level.WARNING,
                  "Guice injected null into {0} (a {1}), please mark it @Nullable."
                      + " Use -Dguice_check_nullable_provides_params=ERROR to turn this into an"
                      + " error.",
                  new Object[] {
                    Messages.formatParameter(dependency), Messages.convert(dependency.getKey())
                  });
            }
            return;
        }
      }
    }

    Object formattedDependency =
        (dependency.getParameterIndex() != -1)
            ? Messages.formatParameter(dependency)
            : StackTraceElements.forMember(dependency.getInjectionPoint().getMember());

    throw InternalProvisionException.create(
            "null returned by binding at %s%n but %s is not @Nullable", source, formattedDependency)
        .addSource(source);
  }

  private final List<Object> sourcesToPrepend = new ArrayList<>();
  private final ImmutableList<Message> errors;

  private InternalProvisionException(Message error) {
    this(ImmutableList.of(error));
  }

  private InternalProvisionException(Iterable<Message> errors) {
    this.errors = ImmutableList.copyOf(errors);
    checkArgument(!this.errors.isEmpty(), "Can't create a provision exception with no errors");
  }

  /**
   * Prepends the given {@code source} to the stack of binding sources for the errors reported in
   * this exception.
   *
   * <p>See {@link Errors#withSource(Object)}
   *
   * <p>It is expected that this method is called as the exception propagates up the stack.
   *
   * @param source
   * @return {@code this}
   */
  InternalProvisionException addSource(Object source) {
    if (source == SourceProvider.UNKNOWN_SOURCE) {
      return this;
    }
    int sz = sourcesToPrepend.size();
    if (sz > 0 && sourcesToPrepend.get(sz - 1) == source) {
      // This is for when there are two identical sources added in a row.  This behavior is copied
      // from Errors.withSource where it can happen when an constructor/provider method throws an
      // exception
      return this;
    }
    sourcesToPrepend.add(source);
    return this;
  }

  ImmutableList<Message> getErrors() {
    ImmutableList.Builder<Message> builder = ImmutableList.builder();
    // reverse them since sources are added as the exception propagates (so the first source is the
    // last one added)
    List<Object> newSources = Lists.reverse(sourcesToPrepend);
    for (Message error : errors) {
      builder.add(Messages.mergeSources(newSources, error));
    }
    return builder.build();
  }

  /** Returns this exception convered to a ProvisionException. */
  public ProvisionException toProvisionException() {
    return new ProvisionException(getErrors());
  }
}
