/**
 * Copyright (C) 2006 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 static com.google.common.base.Preconditions.checkState;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.inject.CreationException;
import com.google.inject.Key;
import com.google.inject.Provider;
import com.google.inject.Scope;
import com.google.inject.TypeLiteral;
import com.google.inject.spi.InjectionPoint;
import com.google.inject.spi.Message;
import java.io.Serializable;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Formatter;
import java.util.List;

/**
 * A collection of error messages. If this type is passed as a method parameter, the method is
 * considered to have executed succesfully only if new errors were not added to this collection.
 *
 * @author jessewilson@google.com (Jesse Wilson)
 */
public final class Errors implements Serializable {

  // TODO(kevinb): gee, ya think we might want to remove this?
  private static final boolean allowNullsBadBadBad
      = "I'm a bad hack".equals(System.getProperty("guice.allow.nulls.bad.bad.bad"));

  // TODO: Provide a policy on what the source line should be for a given member.
  //       Should we prefer the line where the binding was made?
  //       Should we prefer the member?
  // For example, if we bind a class with two scope annotations, is that a problem
  // with the binding, or a problem with the bound class? The catch being that if it's
  // a problem with the binding, then we report a different source line if the class
  // is retrieved via a JIT binding.
  //
  // What about a missing implementation? Is that at the caller?
  // What about injection points?

  /** the stacktrace or member that will be the reference location for new errors */
  private final Object source;

  /** false indicates that new errors should not be added */
  private boolean isMutable = true;
  private final List<Message> errors;
  private final List<InjectionPoint> injectionPoints;

  public Errors() {
    this(SourceProvider.UNKNOWN_SOURCE);
  }

  public Errors(Object source) {
    this.source = source;
    isMutable = true;
    errors = Lists.newArrayList();
    injectionPoints = Lists.newArrayList();
  }

  public Errors(Errors parent, Object source) {
    this.source = source;
    isMutable = parent.isMutable;
    errors = parent.errors;
    injectionPoints = Lists.newArrayList(parent.injectionPoints);
  }

  public Errors userReportedError(String messageFormat, List<Object> arguments) {
    return addMessage(messageFormat, arguments);
  }

  public void pushInjectionPoint(InjectionPoint<?> injectionPoint) {
    injectionPoints.add(injectionPoint);
  }

  public void popInjectionPoint(InjectionPoint<?> injectionPoint) {
    InjectionPoint popped = injectionPoints.remove(injectionPoints.size() - 1);
    checkArgument(injectionPoint == popped);
  }

  /**
   * Returns a new instance that uses {@code source} as a reference point for
   * newly added errors.
   */
  public Errors withSource(Object source) {
    return new Errors(this, source);
  }

  /**
   * We use a fairly generic error message here. The motivation is to share the
   * same message for both bind time errors:
   * <pre><code>Guice.createInjector(new AbstractModule() {
   *   public void configure() {
   *     bind(Runnable.class);
   *   }
   * }</code></pre>
   * ...and at provide-time errors:
   * <pre><code>Guice.createInjector().getInstance(Runnable.class);</code></pre>
   * Otherwise we need to know who's calling when resolving a just-in-time
   * binding, which makes things unnecessarily complex.
   */
  public Errors missingImplementation(Object keyOrType) {
    return addMessage("No implementation for %s was bound.", keyOrType);
  }

  public Errors converterReturnedNull(String stringValue, Object source,
      TypeLiteral<?> type, MatcherAndConverter matchingConverter) {
    return addMessage("Received null converting '%s' (bound at %s) to %s%n"
        + " using %s.",
        stringValue, source, type, matchingConverter);
  }

  public Errors conversionTypeError(String stringValue, Object source, TypeLiteral<?> type,
      MatcherAndConverter matchingConverter, Object converted) {
    return addMessage("Type mismatch converting '%s' (bound at %s) to %s%n"
        + " using %s.%n"
        + " Converter returned %s.",
        stringValue, source, type, matchingConverter, converted);
  }

  public Errors conversionError(String stringValue, Object source,
      TypeLiteral<?> type, MatcherAndConverter matchingConverter, Exception cause) {
    return addMessage(cause, "Error converting '%s' (bound at %s) to %s%n" 
        + " using %s.%n"
        + " Reason: %s",
        stringValue, source, type, matchingConverter, cause);
  }

  public Errors ambiguousTypeConversion(String stringValue, Object source, TypeLiteral<?> type,
      MatcherAndConverter a, MatcherAndConverter b) {
    return addMessage("Multiple converters can convert '%s' (bound at %s) to %s:%n"
        + " %s and%n"
        + " %s.%n"
        + " Please adjust your type converter configuration to avoid overlapping matches.",
        stringValue, source, type, a, b);
  }

  public Errors bindingToProvider() {
    return addMessage("Binding to Provider is not allowed.");
  }

  public Errors subtypeNotProvided(Class<? extends Provider<?>> providerType,
      Class<?> type) {
    return addMessage("%s doesn't provide instances of %s.", providerType, type);
  }

  public Errors notASubtype(Class<?> implementationType, Class<?> type) {
    return addMessage("%s doesn't extend %s.", implementationType, type);
  }

  public Errors recursiveImplementationType() {
    return addMessage("@ImplementedBy points to the same class it annotates.");
  }

  public Errors recursiveProviderType() {
    return addMessage("@ProvidedBy points to the same class it annotates.");
  }

  public Errors missingRuntimeRetention(Object source) {
    return addMessage("Please annotate with @Retention(RUNTIME).%n"
        + " Bound at %s.", source);
  }

  public Errors missingScopeAnnotation() {
    return addMessage("Please annotate with @ScopeAnnotation.");
  }

  public Errors optionalConstructor(Constructor constructor) {
    return addMessage("%s is annotated @Inject(optional=true), "
        + "but constructors cannot be optional.", constructor);
  }

  public Errors cannotBindToGuiceType(String simpleName) {
    return addMessage("Binding to core guice framework type is not allowed: %s.", simpleName);
  }

  public Errors cannotBindToNullInstance() {
    return addMessage("Binding to null instances is not allowed. "
        + "Use toProvider(Providers.of(null)) if this is your intended behaviour.");
  }

  public Errors scopeNotFound(Class<? extends Annotation> scopeAnnotation) {
    return addMessage("No scope is bound to %s.", scopeAnnotation);
  }

  public Errors scopeAnnotationOnAbstractType(
      Class<? extends Annotation> scopeAnnotation, Class<?> type, Object source) {
    return addMessage("%s is annotated with %s, but scope annotations are not supported "
        + "for abstract types.%n Bound at %s.", type, scopeAnnotation, source);
  }

  public Errors misplacedBindingAnnotation(Member member, Annotation bindingAnnotation) {
    return addMessage("%s is annotated with %s, but binding annotations should be applied "
        + "to its parameters instead.", member, bindingAnnotation);
  }

  private static final String CONSTRUCTOR_RULES =
      "Classes must have either one (and only one) constructor "
          + "annotated with @Inject or a zero-argument constructor that is not private.";

  public Errors missingConstructor(Class<?> implementation) {
    return addMessage("Could not find a suitable constructor in %s. " + CONSTRUCTOR_RULES,
        implementation);
  }

  public Errors tooManyConstructors(Class<?> implementation) {
    return addMessage("%s has more than one constructor annotated with @Inject. "
        + CONSTRUCTOR_RULES, implementation);
  }

  public Errors duplicateScopes(Scope existing,
      Class<? extends Annotation> annotationType, Scope scope) {
    return addMessage("Scope %s is already bound to %s. Cannot bind %s.", existing,
        annotationType, scope);
  }

  public Errors missingConstantValues() {
    return addMessage("Missing constant value. Please call to(...).");
  }

  public Errors cannotInjectInnerClass(Class<?> type) {
    return addMessage("Injecting into inner classes is not supported.  "
        + "Please use a 'static' class (top-level or nested) instead of %s.", type);
  }

  public Errors duplicateBindingAnnotations(Member member,
      Class<? extends Annotation> a, Class<? extends Annotation> b) {
    return addMessage("%s has more than one annotation annotated with @BindingAnnotation: "
        + "%s and %s", member, a, b);
  }

  public Errors duplicateScopeAnnotations(
      Class<? extends Annotation> a, Class<? extends Annotation> b) {
    return addMessage("More than one scope annotation was found: %s and %s", a, b);
  }

  public Errors recursiveBinding() {
    return addMessage("Binding points to itself.");
  }

  public Errors bindingAlreadySet(Key<?> key, Object source) {
    return addMessage("A binding to %s was already configured at %s.", key, source);
  }

  public Errors errorInjectingMethod(Throwable cause) {
    return addMessage(cause, "Error injecting method, %s", cause);
  }

  public Errors errorInjectingConstructor(Throwable cause) {
    return addMessage(cause, "Error injecting constructor, %s", cause);
  }

  public Errors errorInProvider(RuntimeException runtimeException, Errors errorsFromException) {
    if (errorsFromException != null) {
      return merge(errorsFromException);
    } else {
      return addMessage(runtimeException, "Error in custom provider, %s", runtimeException);
    }
  }

  public Errors cannotInjectRawProvider() {
    return addMessage("Cannot inject a Provider that has no type parameter");
  }

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

  public Errors makeImmutable() {
    isMutable = false;
    return this;
  }

  public void throwCreationExceptionIfErrorsExist() {
    if (!hasErrors()) {
      return;
    }

    makeImmutable();
    throw new CreationException(getMessages());
  }

  public Errors merge(Errors moreErrors) {
    checkState(isMutable);

    if (moreErrors.errors != this.errors) {
      for (Message message : moreErrors.errors) {
        List<InjectionPoint> injectionPoints = Lists.newArrayList();
        injectionPoints.addAll(this.injectionPoints);
        injectionPoints.addAll(message.getInjectionPoints());
        Object source = message.getSource() != SourceProvider.UNKNOWN_SOURCE
            ? message.getSource()
            : this.source;
        errors.add(new Message(source, message.getMessage(), injectionPoints, message.getCause()));
      }
    }

    return this;
  }

  public void throwIfNecessary() throws ErrorsException {
    if (!hasErrors()) {
      return;
    }

    throw toException();
  }

  public ErrorsException toException() {
    return new ErrorsException(this);
  }

  public boolean hasErrors() {
    return !errors.isEmpty();
  }

  private Errors addMessage(String messageFormat, Object... arguments) {
    return addMessage(null, messageFormat, arguments);
  }

  private Errors addMessage(Throwable cause, String messageFormat, Object... arguments) {
    String message = format(messageFormat, arguments);
    addMessage(new Message(source, message, ImmutableList.copyOf(injectionPoints), cause));
    return this;
  }

  public Errors addMessage(Message message) {
    if (!isMutable) {
      throw new AssertionError();
    }

    errors.add(message);
    return this;
  }

  private String format(String messageFormat, Object... arguments) {
    for (int i = 0; i < arguments.length; i++) {
      arguments[i] = Errors.convert(arguments[i]);
    }
    return String.format(messageFormat, arguments);
  }

  public List<Message> getMessages() {
    List<Message> result = Lists.newArrayList(errors);

    Collections.sort(result, new Comparator<Message>() {
      public int compare(Message a, Message b) {
        return a.getSource().compareTo(b.getSource());
      }
    });

    return result;
  }

  public static String format(String heading, Collection<? extends Message> errorMessages) {
    Formatter fmt = new Formatter().format(heading).format(":%n%n");
    int index = 1;
    for (Message errorMessage : errorMessages) {
      fmt.format("%s) Error at %s:%n", index++, errorMessage.getSource())
         .format(" %s%n", errorMessage.getMessage());

      List<InjectionPoint> injectionPoints = errorMessage.getInjectionPoints();
      for (int i = injectionPoints.size() - 1; i >= 0; i--) {
        InjectionPoint injectionPoint = injectionPoints.get(i);

        Key key = injectionPoint.getKey();
        fmt.format("  while locating %s%n", convert(key));

        Member member = injectionPoint.getMember();
        if (member == null) {
          continue;
        }

        Class<? extends Member> memberType = MoreTypes.memberType(member);
        if (memberType == Field.class) {
          fmt.format("    for field at %s%n", StackTraceElements.forMember(member));

        } else if (memberType == Method.class || memberType == Constructor.class) {
          fmt.format("    for parameter %s at %s%n",
              injectionPoint.getParameterIndex(), StackTraceElements.forMember(member));
        }
      }

      fmt.format("%n");
    }

    return fmt.format("%s error[s]", errorMessages.size()).toString();
  }

  /**
   * Returns {@code value} if it is non-null allowed to be null. Otherwise a message is added and
   * an {@code ErrorsException} is thrown.
   */
  public <T> T checkForNull(T value, Object source, InjectionPoint<?> injectionPoint) 
      throws ErrorsException {
    if (value != null
        || injectionPoint.allowsNull()
        || allowNullsBadBadBad) {
      return value;
    }

    int parameterIndex = injectionPoint.getParameterIndex();
    String parameterName = (parameterIndex != -1)
        ? "parameter " + parameterIndex + " of "
        : "";
    addMessage("null returned by binding at %s%n but %s%s is not @Nullable",
        source, parameterName, injectionPoint.getMember());

    throw toException();
  }

  private static abstract class Converter<T> {

    final Class<T> type;

    Converter(Class<T> type) {
      this.type = type;
    }

    boolean appliesTo(Object o) {
      return type.isAssignableFrom(o.getClass());
    }

    String convert(Object o) {
      return toString(type.cast(o));
    }

    abstract String toString(T t);
  }

  private static final Collection<Converter<?>> converters = ImmutableList.of(
      new Converter<MatcherAndConverter>(MatcherAndConverter.class) {
        public String toString(MatcherAndConverter m) {
          return m.toString();
        }
      },
      new Converter<Class>(Class.class) {
        public String toString(Class c) {
          return c.getName();
        }
      },
      new Converter<Member>(Member.class) {
        public String toString(Member member) {
          return MoreTypes.canonicalize(member).toString();
        }
      },
      new Converter<Key>(Key.class) {
        public String toString(Key k) {
          StringBuilder result = new StringBuilder();
          result.append(k.getTypeLiteral());
          if (k.getAnnotationType() != null) {
            result.append(" annotated with ");
            result.append(k.getAnnotation() != null ? k.getAnnotation() : k.getAnnotationType());
          }
          return result.toString();
        }
      });

  public static Object convert(Object o) {
    for (Converter<?> converter : converters) {
      if (converter.appliesTo(o)) {
        return converter.convert(o);
      }
    }
    return o;
  }
}
