// Copyright 2015 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.lib.syntax;

import com.google.common.base.Joiner;
import com.google.devtools.build.lib.events.Location;
import com.google.devtools.build.lib.util.Preconditions;

import java.util.Deque;
import java.util.LinkedList;
import java.util.Objects;

/**
 * EvalException with a stack trace.
 */
public class EvalExceptionWithStackTrace extends EvalException {

  private StackTraceElement mostRecentElement;

  public EvalExceptionWithStackTrace(Exception original, ASTNode culprit) {
    super(extractLocation(original, culprit), getNonEmptyMessage(original), getCause(original));
    registerNode(culprit);
  }

  @Override
  public boolean canBeAddedToStackTrace() {
    // Doesn't make any sense to add this exception to another instance of
    // EvalExceptionWithStackTrace.
    return false;
  }

  /**
   * Returns the appropriate location for this exception.
   *
   * <p>If the {@code ASTNode} has a valid location, this one is used. Otherwise, we try to get the
   * location of the exception.
   */
  private static Location extractLocation(Exception original, ASTNode culprit) {
    if (culprit != null && culprit.getLocation() != null) {
      return culprit.getLocation();
    }
    return (original instanceof EvalException) ? ((EvalException) original).getLocation() : null;
  }

  /**
   * Returns the "real" cause of this exception.
   *
   * <p>If the original exception is an EvalException, its cause is returned.
   * Otherwise, the original exception itself is seen as the cause for this exception.
   */
  private static Throwable getCause(Exception ex) {
    return (ex instanceof EvalException) ? ex.getCause() : ex;
  }

  /**
   * Adds an entry for the given {@code ASTNode} to the stack trace.
   */
  public void registerNode(ASTNode node) {
    addStackFrame(node.toString().trim(), node.getLocation());
  }

  /**
   * Makes sure the stack trace is rooted in a function call.
   *
   * In some cases (rule implementation application, aspect implementation application)
   * bazel calls into the function directly (using BaseFunction.call). In that case, since
   * there is no FuncallExpression to evaluate, stack trace mechanism cannot record this call.
   * This method allows to augument the stack trace with information about the call.
   */
  public void registerPhantomFuncall(
      String funcallDescription, Location location, BaseFunction function) {
    /*
     *
     * We add two new frames to the stack:
     * 1. Pseudo-function call (for example, rule definition)
     * 2. Function entry (Rule implementation)
     *
     * Similar to Python, all functions that were entered (except for the top-level ones) appear
     * twice in the stack trace output. This would lead to the following trace:
     *
     * File BUILD, line X, in <module>
     *     rule_definition()
     * File BUILD, line X, in rule_definition
     *     rule_implementation()
     * File bzl, line Y, in rule_implementation
     *     ...
     *
     * Please note that lines 3 and 4 are quite confusing since a) the transition from
     * rule_definition to rule_implementation happens internally and b) the locations do not make
     * any sense.
     * Consequently, we decided to omit lines 3 and 4 from the output via canPrint = false:
     *
     * File BUILD, line X, in <module>
     *     rule_definition()
     * File bzl, line Y, in rule_implementation
     *     ...
     *
     * */
    addStackFrame(function.getName(), function.getLocation());
    addStackFrame(funcallDescription, location, false);
  }

  /**
   * Adds a line for the given frame.
   */
  private void addStackFrame(String label, Location location, boolean canPrint) {
    // We have to watch out for duplicate since ExpressionStatements add themselves twice:
    // Statement#exec() calls Expression#eval(), both of which call this method.
    if (mostRecentElement != null && isSameLocation(location, mostRecentElement.getLocation())) {
      return;
    }
    mostRecentElement = new StackTraceElement(label, location, mostRecentElement, canPrint);
  }

  /**
   * Checks two locations for equality in paths and start offsets.
   *
   * <p> LexerLocation#equals cannot be used since it cares about different end offsets.
   */
  private boolean isSameLocation(Location first, Location second) {
    try {
      return Objects.equals(first.getPath(), second.getPath())
          && Objects.equals(first.getStartOffset(), second.getStartOffset());
    } catch (NullPointerException ex) {
      return first == second;
    }
  }

  private void addStackFrame(String label, Location location)   {
    addStackFrame(label, location, true);
  }

  /**
   * Returns the exception message without the stack trace.
   */
  public String getOriginalMessage() {
    return super.getMessage();
  }

  @Override
  public String getMessage() {
    return print();
  }

  @Override
  public String print() {
    // Currently, we do not limit the text length per line.
    return print(StackTracePrinter.INSTANCE);
  }

  /**
   *  Prints the stack trace iff it contains more than just one built-in function.
   */
  public String print(StackTracePrinter printer) {
    return canPrintStackTrace()
        ? printer.print(getOriginalMessage(), mostRecentElement)
        : getOriginalMessage();
  }

  /**
   * Returns true when there is at least one non-built-in element.
   */
  protected boolean canPrintStackTrace() {
    return mostRecentElement != null && mostRecentElement.getCause() != null;
  }

  /**
   * An element in the stack trace which contains the name of the offending function / rule /
   * statement and its location.
   */
  protected static final class StackTraceElement {
    private final String label;
    private final Location location;
    private final StackTraceElement cause;
    private final boolean canPrint;

    StackTraceElement(String label, Location location, StackTraceElement cause, boolean canPrint) {
      this.label = label;
      this.location = location;
      this.cause = cause;
      this.canPrint = canPrint;
    }

    String getLabel() {
      return label;
    }

    Location getLocation() {
      return location;
    }

    StackTraceElement getCause() {
      return cause;
    }

    boolean canPrint() {
      return canPrint;
    }

    @Override
    public String toString() {
      return String.format(
          "%s @ %s -> %s", label, location, (cause == null) ? "null" : cause.toString());
    }
  }

  /**
   * Singleton class that prints stack traces similar to Python.
   */
  public enum StackTracePrinter {
    INSTANCE;

    /**
     * Turns the given message and StackTraceElements into a string.
     */
    public final String print(String message, StackTraceElement mostRecentElement) {
      Deque<String> output = new LinkedList<>();

      // Adds dummy element for the rule call that uses the location of the top-most function.
      mostRecentElement = new StackTraceElement("", mostRecentElement.getLocation(),
          (mostRecentElement.getCause() == null) ? null : mostRecentElement, true);

      while (mostRecentElement != null) {
        if (mostRecentElement.canPrint()) {
          String entry = print(mostRecentElement);
          if (entry != null && entry.length() > 0) {
            addEntry(output, entry);
          }
        }

        mostRecentElement = mostRecentElement.getCause();
      }

      addMessage(output, message);
      return Joiner.on("\n").join(output);
    }

    /**
     * Returns the location of the given element or Location.BUILTIN if the element is null.
     */
    private Location getLocation(StackTraceElement element) {
      return (element == null) ? Location.BUILTIN : element.getLocation();
    }

    /**
     * Returns the string representation of the given element.
     */
    protected String print(StackTraceElement element) {
      // Similar to Python, the first (most-recent) entry in the stack frame is printed only once.
      // Consequently, we skip it here.
      if (element.getCause() == null) {
        return "";
      }

      // Prints a two-line string, similar to Python.
      Location location = getLocation(element.getCause());
      return String.format(
          "\tFile \"%s\", line %d%s%n\t\t%s",
          printPath(location),
          getLine(location),
          printFunction(element.getLabel()),
          element.getCause().getLabel());
    }

    private String printFunction(String func) {
      if (func.isEmpty()) {
        return "";
      }

      int pos = func.indexOf('(');
      return String.format(", in %s", (pos < 0) ? func : func.substring(0, pos));
    }

    private String printPath(Location loc) {
      return (loc == null || loc.getPath() == null) ? "<unknown>" : loc.getPath().getPathString();
    }

    private int getLine(Location loc) {
      return (loc == null || loc.getStartLineAndColumn() == null)
          ? 0 : loc.getStartLineAndColumn().getLine();
    }

    /**
     * Adds the given string to the specified Deque.
     */
    protected void addEntry(Deque<String> output, String toAdd) {
      output.addLast(toAdd);
    }

    /**
     * Adds the given message to the given output dequeue after all stack trace elements have been
     * added.
     */
    protected void addMessage(Deque<String> output, String message) {
      output.addFirst("Traceback (most recent call last):");
      output.addLast(message);
    }
  }

  /**
   * Returns a non-empty message for the given exception.
   *
   * <p> If the exception itself does not have a message, a new message is constructed from the
   * exception's class name.
   * For example, an IllegalArgumentException will lead to "Illegal Argument".
   * Additionally, the location in the Java code will be added, if applicable,
   */
  private static String getNonEmptyMessage(Exception original) {
    Preconditions.checkNotNull(original);
    String msg = original.getMessage();
    if (msg != null && !msg.isEmpty()) {
      return msg;
    }

    char[] name = original.getClass().getSimpleName().replace("Exception", "").toCharArray();
    boolean first = true;
    StringBuilder builder = new StringBuilder();

    for (char current : name) {
      if (Character.isUpperCase(current) && !first) {
        builder.append(" ");
      }
      builder.append(current);
      first = false;
    }

    java.lang.StackTraceElement[] trace = original.getStackTrace();
    if (trace.length > 0) {
      builder.append(String.format(": %s.%s() in %s:%d", getShortClassName(trace[0]),
          trace[0].getMethodName(), trace[0].getFileName(), trace[0].getLineNumber()));
    }

    return builder.toString();
  }

  private static String getShortClassName(java.lang.StackTraceElement element) {
    String name = element.getClassName();
    int pos = name.lastIndexOf('.');
    return (pos < 0) ? name : name.substring(pos + 1);
  }
}
