/*
 * Copyright 2009 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.gwt.core.client.impl;

import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.core.client.JsArray;
import com.google.gwt.core.client.JsArrayString;

/**
 * Encapsulates logic to create a stack trace. This class should only be used in
 * Production Mode.
 */
public class StackTraceCreator {

  /**
   * Maximum # of frames to look for {@link Throwable#fillInStackTrace()} in the generated stack
   * trace. This is just a safe guard just in case if {@code fillInStackTrace} doesn't show up in
   * the stack trace for some reason.
   */
  private static final int DROP_FRAME_LIMIT = 5;

  /**
   * Line number used in a stack trace when it is unknown.
   */
  private static final int LINE_NUMBER_UNKNOWN = -1;

  /**
   * Replacement for function names that cannot be extracted from a stack.
   */
  private static final String ANONYMOUS = "anonymous";

  /**
   * Replacement for class or file names that cannot be extracted from a stack.
   */
  private static final String UNKNOWN = "Unknown";

  /**
   * This class acts as a deferred-binding hook point to allow more optimal versions to be
   * substituted.
   */
  abstract static class Collector {

    public abstract void collect(Object t, Object jsThrown);

    public abstract StackTraceElement[] getStackTrace(Object t);
  }

  /**
   * This legacy {@link Collector} simply crawls <code>arguments.callee.caller</code> for browsers
   * that doesn't support {@code Error.stack} property.
   */
  static class CollectorLegacy extends Collector {

    @Override
    public native void collect(Object t, Object thrownIgnored) /*-{
      var seen = {};
      t.fnStack = [];

      // Ignore the collect() call
      var callee = arguments.callee.caller;
      while (callee) {
        var name = @StackTraceCreator::getFunctionName(*)(callee);
        t.fnStack.push(name);

        // Avoid infinite loop by associating names to function objects.  We
        // record each caller in the withThisName variable to handle functions
        // with identical names but separate identity (such as 'anonymous')
        var keyName = ':' + name;
        var withThisName = seen[keyName];
        if (withThisName) {
          var i, j;
          for (i = 0, j = withThisName.length; i < j; i++) {
            if (withThisName[i] === callee) {
              return;
            }
          }
        }

        (withThisName || (seen[keyName] = [])).push(callee);
        callee = callee.caller;
      }
    }-*/;

    @Override
    public StackTraceElement[] getStackTrace(Object t) {
      JsArrayString stack = getFnStack(t);

      int length = stack.length();
      StackTraceElement[] stackTrace = new StackTraceElement[length];
      for (int i = 0; i < length; i++) {
        stackTrace[i] = new StackTraceElement(UNKNOWN, stack.get(i), null, LINE_NUMBER_UNKNOWN);
      }
      return stackTrace;
    }
  }

  /**
   * Collaborates with JsStackEmulator.
   */
  static final class CollectorEmulated extends Collector {

    @Override
    public native void collect(Object t, Object jsThrownIgnored) /*-{
      t.fnStack = [];
      for (var i = 0; i < $stackDepth; i++) {
        var location = $location[i];
        var fn = $stack[i];
        var name = fn ? @StackTraceCreator::getFunctionName(*)(fn) : @StackTraceCreator::ANONYMOUS;

        // Reverse the order
        t.fnStack[$stackDepth - i - 1] = [name, location];
      }
    }-*/;

    @Override
    public StackTraceElement[] getStackTrace(Object t) {
      JsArray<JsArrayString> stack = getFnStack(t).cast();

      StackTraceElement[] stackTrace = new StackTraceElement[stack.length()];
      for (int i = 0; i < stackTrace.length; i++) {
        JsArrayString frame = stack.get(i);
        String name = frame.get(0);
        String location = frame.get(1);

        String fileName = null;
        int lineNumber = LINE_NUMBER_UNKNOWN;
        if (location != null) {
          int idx = location.indexOf(':');
          if (idx != -1) {
            fileName = location.substring(0, idx);
            lineNumber = parseInt(location.substring(idx + 1));
          } else {
            lineNumber = parseInt(location);
          }
        }
        stackTrace[i] = new StackTraceElement(UNKNOWN, name, fileName, lineNumber);
      }
      return stackTrace;
    }
  }

  /**
   * Modern browsers provide a <code>stack</code> property in thrown objects.
   */
  static class CollectorModern extends Collector {

    static {
      increaseStackTraceLimit();
    }

    // As of today, only available in IE10+ and Chrome.
    private static native void increaseStackTraceLimit() /*-{
      // TODO(cromwellian) make this a configurable?
      Error.stackTraceLimit = 64;
    }-*/;

    @Override
    public native void collect(Object t, Object jsThrown) /*-{
      // TODO(goktug): optimize for Chrome by not evaluating stack (use Error.captureStackTrace)
      t.stack = (jsThrown && jsThrown.stack) || @StackTraceCreator::makeException()().stack;
     }-*/;

    @Override
    public StackTraceElement[] getStackTrace(Object t) {
      JsArrayString stack = split(t);

      // We are in script-mode - let the array auto grow.
      StackTraceElement[] stackTrace = new StackTraceElement[0];
      int addIndex = 0, length = stack.length();

      if (length == 0) {
        // Nothing to parse...
        return stackTrace;
      }

      // Chrome & IE10+ contains the error msg as the first line of stack (iOS, Firefox doesn't).
      StackTraceElement ste = parse(stack.get(0));
      if (!ste.getMethodName().equals(ANONYMOUS)) {
        stackTrace[addIndex++] = ste;
      }

      // Parse and put the rest of the elements in to the stack trace.
      for (int i = 1; i < length; i++) {
        stackTrace[addIndex++] = parse(stack.get(i));
      }

      return stackTrace;
    }

    /**
     * Parses a stack trace line from the browser and returns a new {@link StackTraceElement}
     * constructed with the extracted data.
     */
    private StackTraceElement parse(String stString) {
      String location = "";

      if (stString.isEmpty()) {
        return createSte(UNKNOWN, ANONYMOUS, LINE_NUMBER_UNKNOWN, -1);
      }

      String toReturn = stString.trim();

      // Strip the "at " prefix:
      if (toReturn.startsWith("at ")) {
        toReturn = toReturn.substring(3);
      }

      toReturn = stripSquareBrackets(toReturn);

      int index = toReturn.indexOf("(");
      if (index == -1) {
        // No bracketed items found, try '@' (used by iOS & Firefox).
        index = toReturn.indexOf("@");
        if (index == -1) {
          // No bracketed items nor '@' found, hence no function name available
          location = toReturn;
          toReturn = "";
        } else {
          location = toReturn.substring(index + 1).trim();
          toReturn = toReturn.substring(0, index).trim();
        }
      } else {
        // Bracketed items found: strip them off, parse location info
        int closeParen = toReturn.indexOf(")", index);
        location = toReturn.substring(index + 1, closeParen);
        toReturn = toReturn.substring(0, index).trim();
      }

      // Strip the Type off t
      index = toReturn.indexOf('.');
      if (index != -1) {
        toReturn = toReturn.substring(index + 1);
      }

      final String ieAnonymousFunctionName = "Anonymous function";
      if (toReturn.isEmpty() || toReturn.equals(ieAnonymousFunctionName)) {
        toReturn = ANONYMOUS;
      }

      // colon between line and column
      int lastColonIndex = location.lastIndexOf(':');
      // colon between file url and line number
      int endFileUrlIndex = location.lastIndexOf(':', lastColonIndex - 1);

      int line = LINE_NUMBER_UNKNOWN;
      int col = -1;
      String fileName = UNKNOWN;

      if (lastColonIndex != -1 && endFileUrlIndex != -1) {
        fileName = location.substring(0, endFileUrlIndex);
        line = parseInt(location.substring(endFileUrlIndex + 1, lastColonIndex));
        col = parseInt(location.substring(lastColonIndex + 1));
      }

      return createSte(fileName, toReturn, line, col);
    }

    protected StackTraceElement createSte(String fileName, String method, int line, int col) {
      return new StackTraceElement(UNKNOWN, method, fileName + "@" + col,
          line < 0 ? LINE_NUMBER_UNKNOWN : line);
    }

    private native String stripSquareBrackets(String toReturn) /*-{
      return toReturn.replace(/\[.*?\]/g,"")
    }-*/;
  }

  /**
   * Subclass that forces reported line numbers to -1 (fetch from symbolMap) if source maps are
   * disabled.
   */
  static class CollectorModernNoSourceMap extends CollectorModern {
    @Override
    protected StackTraceElement createSte(String fileName, String method, int line, int col) {
      return new StackTraceElement(UNKNOWN, method, fileName, LINE_NUMBER_UNKNOWN);
    }
  }

  private static native int parseInt(String number) /*-{
    return parseInt(number) || @StackTraceCreator::LINE_NUMBER_UNKNOWN;
  }-*/;

  /**
   * When compiler.stackMode = strip, we stub out the collector.
   */
  static class CollectorNull extends Collector {
    @Override
    public void collect(Object ignored, Object jsThrownIgnored) {
      // Nothing to do
    }

    @Override
    public StackTraceElement[] getStackTrace(Object ignored) {
      return new StackTraceElement[0];
    }
  }

  /**
   * Collect necessary information to construct stack trace trace later in time.
   */
  public static void captureStackTrace(Throwable throwable, Object reference) {
    collector.collect(throwable, reference);
  }

  public static StackTraceElement[] constructJavaStackTrace(Throwable thrown) {
    StackTraceElement[] stackTrace = collector.getStackTrace(thrown);
    return dropInternalFrames(stackTrace);
  }

  private static StackTraceElement[] dropInternalFrames(StackTraceElement[] stackTrace) {
    final String dropFrameUntilFnName = Impl.getNameOf("@java.lang.Throwable::fillInStackTrace()");

    int numberOfFrameToSearch = Math.min(stackTrace.length, DROP_FRAME_LIMIT);
    for (int i = 0; i < numberOfFrameToSearch; i++) {
      if (stackTrace[i].getMethodName().equals(dropFrameUntilFnName)) {
        return splice(stackTrace, i + 1);
      }
    }

    return stackTrace;
  }

  // Visible for testing
  static final Collector collector;

  static {
    // Ensure old Safari falls back to legacy Collector implementation.
    boolean enforceLegacy = !supportsErrorStack();
    Collector c = GWT.create(Collector.class);
    collector = (c instanceof CollectorModern && enforceLegacy) ? new CollectorLegacy() : c;
  }

  private static native boolean supportsErrorStack() /*-{
    // Error.stackTraceLimit is cheaper to check and available in both IE and Chrome
    return !!Error.stackTraceLimit || "stack" in @StackTraceCreator::makeException()();
  }-*/;

  private static native JavaScriptObject makeException() /*-{
    // TODO(goktug): new Error().stack is broken for htmlunit:
    // https://sourceforge.net/p/htmlunit/bugs/1606/
    try {
      null.a();
    } catch (e) {
      return e;
    }
  }-*/;

  private static native JsArrayString getFnStack(Object e) /*-{
    return (e && e.fnStack && e.fnStack instanceof Array) ? e.fnStack : [];
  }-*/;

  private static native String getFunctionName(JavaScriptObject fn) /*-{
    return fn.name || (fn.name = @StackTraceCreator::extractFunctionName(*)(fn.toString()));
  }-*/;

  // Visible for testing
  static native String extractFunctionName(String fnName) /*-{
    var fnRE = /function(?:\s+([\w$]+))?\s*\(/;
    var match = fnRE.exec(fnName);
    return (match && match[1]) || @StackTraceCreator::ANONYMOUS;
  }-*/;

  private static native JsArrayString split(Object e) /*-{
    return e.stack ? e.stack.split('\n') : [];
  }-*/;

  private static native <T> T splice(T arr, int length) /*-{
    (arr.length >= length) && arr.splice(0, length);
    return arr;
  }-*/;
}
