// Copyright 2014 The Bazel Authors. All rights reserved.
//
// 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.devtools.build.skyframe;

import com.google.common.base.MoreObjects;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.devtools.build.skyframe.SkyFunctionException.ReifiedSkyFunctionException;
import java.util.Collection;
import java.util.Objects;
import javax.annotation.Nullable;

/**
 * Information about why a {@link SkyValue} failed to evaluate successfully.
 *
 * <p>This is intended only for use in alternative {@code MemoizingEvaluator} implementations.
 */
public class ErrorInfo {
  /** Create an ErrorInfo from a {@link ReifiedSkyFunctionException}. */
  public static ErrorInfo fromException(
      ReifiedSkyFunctionException skyFunctionException, boolean isTransitivelyTransient) {
    Exception rootCauseException = skyFunctionException.getCause();
    return new ErrorInfo(
        Preconditions.checkNotNull(rootCauseException, "Cause is null"),
        /*cycles=*/ ImmutableList.of(),
        skyFunctionException.isTransient(),
        isTransitivelyTransient || skyFunctionException.isTransient(),
        skyFunctionException.isCatastrophic());
  }

  /** Create an ErrorInfo from a {@link CycleInfo}. */
  public static ErrorInfo fromCycle(CycleInfo cycleInfo) {
    return new ErrorInfo(
        /*exception=*/ null,
        ImmutableList.of(cycleInfo),
        /*isDirectlyTransient=*/ false,
        /*isTransitivelyTransient=*/ false,
        /*isCatastrophic=*/ false);
  }

  /** A wrapper that indicates that there's a value associated with the ErrorInfo's SkyKey. */
  public static ErrorInfo withValue(ErrorInfo wrapped) {
    return new ErrorInfoWithValue(
        wrapped.getException(),
        wrapped.getCycleInfo(),
        wrapped.isDirectlyTransient(),
        wrapped.isTransitivelyTransient(),
        wrapped.isCatastrophic());
  }

  /** Create an ErrorInfo from a collection of existing errors. */
  public static ErrorInfo fromChildErrors(SkyKey currentValue, Collection<ErrorInfo> childErrors) {
    Preconditions.checkNotNull(currentValue, "currentValue must not be null");
    Preconditions.checkState(
        !childErrors.isEmpty(), "childErrors may not be empty %s", currentValue);

    ImmutableList.Builder<CycleInfo> cycleBuilder = ImmutableList.builder();
    Exception representativeException = null;
    boolean representativeExceptionCameWithValue = false;
    boolean isTransitivelyTransient = false;
    boolean isCatastrophic = false;
    for (ErrorInfo child : childErrors) {
      // Child errors that come with a value indicates that the error was somehow tolerated.
      // Priorities should be given to those without values.
      // Otherwise, choose the first error.
      if (representativeException == null
          || (representativeExceptionCameWithValue && child.exception != null)) {
        representativeException = child.exception;
        representativeExceptionCameWithValue = child.hasValue();
      }
      cycleBuilder.addAll(CycleInfo.prepareCycles(currentValue, child.cycles));
      isTransitivelyTransient |= child.isTransitivelyTransient;
      isCatastrophic |= child.isCatastrophic;
    }

    return new ErrorInfo(
        representativeException,
        cycleBuilder.build(),
        /* isDirectlyTransient= */ false,
        isTransitivelyTransient,
        isCatastrophic);
  }

  /** Whether the SkyKey of this ErrorInfo has a corresponding SkyValue. */
  boolean hasValue() {
    return false;
  }

  @Nullable private final Exception exception;
  private final ImmutableList<CycleInfo> cycles;
  private final boolean isDirectlyTransient;
  private final boolean isTransitivelyTransient;
  private final boolean isCatastrophic;

  @SuppressWarnings("LenientFormatStringValidation")
  public ErrorInfo(
      @Nullable Exception exception,
      ImmutableList<CycleInfo> cycles,
      boolean isDirectlyTransient,
      boolean isTransitivelyTransient,
      boolean isCatastrophic) {
    this.exception = exception;
    this.cycles = cycles;
    this.isDirectlyTransient = isDirectlyTransient;
    this.isTransitivelyTransient = isTransitivelyTransient;
    this.isCatastrophic = isCatastrophic;
    // Expected 0 args, but got 1.
    Preconditions.checkArgument(
        exception != null || !cycles.isEmpty(),
        "At least one of exception and cycles must be present",
        this);
    // Expected 0 args, but got 1.
    Preconditions.checkArgument(
        !isDirectlyTransient || isTransitivelyTransient,
        "Cannot be directly transient but not transitively transient",
        this);
  }

  @Override
  public boolean equals(Object obj) {
    if (this == obj) {
      return true;
    }
    if (!(obj instanceof ErrorInfo)) {
      return false;
    }

    ErrorInfo other = (ErrorInfo) obj;

    if (!Objects.equals(cycles, other.cycles)) {
      return false;
    }

    // Don't check the specific exception as most exceptions don't implement equality but at least
    // check their types and messages are the same.
    if (exception != other.exception) {
      if (exception == null || other.exception == null) {
        return false;
      }
      // Class objects are singletons with a single class loader.
      if (exception.getClass() != other.exception.getClass()) {
        return false;
      }
      if (!Objects.equals(exception.getMessage(), other.exception.getMessage())) {
        return false;
      }
    }

    return isDirectlyTransient == other.isDirectlyTransient
        && isTransitivelyTransient == other.isTransitivelyTransient
        && isCatastrophic == other.isCatastrophic;
  }

  @Override
  public int hashCode() {
    return Objects.hash(
        exception == null ? null : exception.getClass(),
        exception == null ? "" : exception.getMessage(),
        cycles,
        isDirectlyTransient,
        isTransitivelyTransient,
        isCatastrophic);
  }

  @Override
  public String toString() {
    return MoreObjects.toStringHelper(this)
        .add("exception", exception)
        .add("cycles", cycles)
        .add("isCatastrophic", isCatastrophic)
        .add("isDirectlyTransient", isDirectlyTransient)
        .add("isTransitivelyTransient", isTransitivelyTransient)
        .toString();
  }

  /**
   * The exception thrown when building a value. May be null if value's only error is depending
   * on a cycle.
   *
   * <p>The exception is used for reporting and thus may ultimately be rethrown by the caller.
   * As well, during a --nokeep_going evaluation, if an error value is encountered from an earlier
   * --keep_going build, the exception to be thrown is taken from here.
   */
  @Nullable public Exception getException() {
    return exception;
  }

  /**
   * Any cycles found when building this value.
   *
   * <p>If there are a large number of cycles, only a limited number are returned here.
   *
   * <p>If this value has a child through which there are multiple paths to the same cycle, only one
   * path is returned here. However, if there are multiple paths to the same cycle, each of which
   * goes through a different child, each of them is returned here.
   */
  public ImmutableList<CycleInfo> getCycleInfo() {
    return cycles;
  }

  /**
   * Returns true iff the error is directly transient, i.e. if there was a transient error
   * encountered during the computation itself.
   *
   * <p>A return of {@code true} implies that {@link #isTransitivelyTransient()} is also {@code
   * true}.
   */
  public boolean isDirectlyTransient() {
    return isDirectlyTransient;
  }

  /**
   * Returns true iff the error is transitively transient, i.e. if retrying the same computation
   * could lead to a different result.
   */
  public boolean isTransitivelyTransient() {
    return isTransitivelyTransient;
  }

  /**
   * Returns true iff the error is catastrophic, i.e. it should halt even for a keepGoing update()
   * call.
   */
  public boolean isCatastrophic() {
    return isCatastrophic;
  }

  /**
   * Indicates that there's a value associated with the SkyKey that owns this ErrorInfo.
   *
   * <p>These should be de-prioritized among child ErrorInfos in {@link #fromChildErrors}.
   */
  private static class ErrorInfoWithValue extends ErrorInfo {
    public ErrorInfoWithValue(
        @Nullable Exception exception,
        ImmutableList<CycleInfo> cycles,
        boolean isDirectlyTransient,
        boolean isTransitivelyTransient,
        boolean isCatastrophic) {
      super(exception, cycles, isDirectlyTransient, isTransitivelyTransient, isCatastrophic);
    }

    @Override
    boolean hasValue() {
      return true;
    }
  }
}
