/*
 * Copyright 2008 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.Duration;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.GWT.UncaughtExceptionHandler;
import com.google.gwt.core.client.GwtScriptOnly;
import com.google.gwt.core.client.JavaScriptException;
import com.google.gwt.core.client.JavaScriptObject;

/**
 * Private implementation class for GWT core. This API is should not be
 * considered public or stable.
 */
public final class Impl {

  static {
    if (GWT.isScript() && StackTraceCreator.collector != null) {
      // Just enforces loading of StackTraceCreator early on, nothing else to do here...
    }
  }

  private static final int WATCHDOG_ENTRY_DEPTH_CHECK_INTERVAL_MS = 2000;

  /**
   * Used by {@link #entry0(Object, Object)} to handle reentrancy.
   */
  private static int entryDepth = 0;

  /**
   * TimeStamp indicating last scheduling of the entry depth watchdog.
   */
  private static double watchdogEntryDepthLastScheduled;

  /**
   * Timer id of the entry depth watchdog. -1 if not scheduled.
   */
  private static int watchdogEntryDepthTimerId = -1;

  /**
   * This method should be used whenever GWT code is entered from a JS context
   * and there is no GWT code in the same module on the call stack. Examples
   * include event handlers, exported methods, and module initialization.
   * <p>
   * The GWT compiler and Development Mode will provide a module-scoped
   * variable, <code>$entry</code>, which is an alias for this method.
   * <p>
   * This method can be called reentrantly, which will simply delegate to the
   * function.
   * <p>
   * The function passed to this method will be invoked via
   * <code>Function.apply()</code> with the current <code>this</code> value and
   * the invocation arguments passed to <code>$entry</code>.
   *
   * @param jsFunction a JS function to invoke, which is typically a JSNI
   *          reference to a static Java method
   * @return the value returned when <code>jsFunction</code> is invoked, or
   *         <code>undefined</code> if the UncaughtExceptionHandler catches an
   *         exception raised by <code>jsFunction</code>
   */
  public static native JavaScriptObject entry(JavaScriptObject jsFunction) /*-{
    return function() {
      if (@com.google.gwt.core.client.GWT::isScript()()) {
        return @Impl::entry0(*)(jsFunction, this, arguments);
      } else {
        var _ = @Impl::entry0(*)(jsFunction, this, arguments);
        if (_ != null) {
          // Unwraps for Development Mode (see #apply())
          _ = _.val;
        }
        return _;
      }
    };
  }-*/;

  public static native String getHostPageBaseURL() /*-{
    var s = $doc.location.href;

    // Pull off any hash.
    var i = s.indexOf('#');
    if (i != -1)
      s = s.substring(0, i);

    // Pull off any query string.
    i = s.indexOf('?');
    if (i != -1)
      s = s.substring(0, i);

    // Rip off everything after the last slash.
    i = s.lastIndexOf('/');
    if (i != -1)
      s = s.substring(0, i);

    // Ensure a final slash if non-empty.
    return s.length > 0 ? s + "/" : "";
  }-*/;

  public static native String getModuleBaseURL() /*-{
    // Check to see if DevModeRedirectHook has set an alternate value.
    // The key should match DevModeRedirectHook.js.
    var key = "__gwtDevModeHook:" + $moduleName + ":moduleBase";
    var global = $wnd || self;
    return global[key] || $moduleBase;
  }-*/;

  public static native String getModuleBaseURLForStaticFiles() /*-{
    return $moduleBase;
  }-*/;

  public static native String getModuleName() /*-{
    return $moduleName;
  }-*/;

  /**
   * Returns the obfuscated name of members in the compiled output. This is a thin wrapper around
   * JNameOf AST nodes and is therefore meaningless to implement in Development Mode.
   * If the requested member is a method, the method will not be devirtualized, inlined or prunned.
   *
   * @param jsniIdent a string literal specifying a type, field, or method. Raw
   *          type names may also be used to obtain the name of the type's seed
   *          function.
   * @return the name by which the named member can be accessed at runtime, or
   *         <code>null</code> if the requested member has been pruned from the
   *         output.
   */
  public static String getNameOf(String jsniIdent) {
    /*
     * In Production Mode, the compiler directly replaces calls to this method
     * with a string literal expression.
     */
    assert !GWT.isScript() : "ReplaceRebinds failed to replace this method";
    throw new UnsupportedOperationException(
        "Impl.getNameOf() is unimplemented in Development Mode");
  }

  public static native String getPermutationStrongName() /*-{
    return $strongName;
  }-*/;

  /**
   * UncaughtExceptionHandler that is used by unit tests to spy on uncaught
   * exceptions.
   */
  private static UncaughtExceptionHandler uncaughtExceptionHandlerForTest;

  /**
   * Set an uncaught exception handler to spy on uncaught exceptions in unit
   * tests.
   * <p>
   * Setting this method will not interfere with any exception handling logic;
   * i.e. {@link GWT#getUncaughtExceptionHandler()} will still return null if a
   * handler is not set via {@link GWT#setUncaughtExceptionHandler}.
   */
  public static void setUncaughtExceptionHandlerForTest(
      UncaughtExceptionHandler handler) {
    uncaughtExceptionHandlerForTest = handler;
  }

  private static boolean onErrorInitialized;

  public static void maybeInitializeWindowOnError() {
    if ("IGNORE".equals(System.getProperty("gwt.uncaughtexceptionhander.windowonerror"))) {
      return;
    }
    if (onErrorInitialized) {
      return;
    }
    onErrorInitialized = true;
    boolean alwaysReport =
        "REPORT"
            .equals(System.getProperty("gwt.uncaughtexceptionhander.windowonerror"));
    registerWindowOnError(alwaysReport);
  }

  // Make sure dev mode does not try to parse the JSNI method since it contains a reference to
  // Throwable.of which is not standard Java
  @SuppressWarnings("deprecation")
  @GwtScriptOnly
  public static native void registerWindowOnError(boolean reportAlways) /*-{
    function errorHandler(msg, url, line, column, error) {
      // IE8, IE9, IE10, safari 9, do not have an error passed
      if (!error) {
        error = msg + " (" + url + ":" + line
        // IE8 and IE9 do not have the column number
        if (column) {
          error += ":" + column
        }
        error += ")";
      }

      var throwable = @java.lang.Throwable::of(*)(error);
      @Impl::reportWindowOnError(*)(throwable);
    };

    function addOnErrorHandler(windowRef) {
      var origHandler = windowRef.onerror;
      if (origHandler && !reportAlways) {
        return;
      }

      windowRef.onerror = function() {
        errorHandler.apply(this, arguments);
        if (origHandler) {
          origHandler.apply(this, arguments);
        }
        return false;
      };
    }

    // Note we need to trap both window.onerror and $wnd.onerror
    // Chrome 58 & Safari (10.1) & HtmlUnit uses $wnd.error,
    // while FF (53) /IE (even edge) listens on window.error
    addOnErrorHandler($wnd);
    addOnErrorHandler(window);
  }-*/;

  private static void reportWindowOnError(Throwable e) {
    // If the error is coming from window.onerror that we registered on, we can not report it
    // back to the browser since we would end up being called again
    reportUncaughtException(e, false);
  }

  public static void reportUncaughtException(Throwable e) {
    reportUncaughtException(e, true);
  }

  private static void reportUncaughtException(
      Throwable e, boolean reportSwallowedExceptionToBrowser) {
    if (Impl.uncaughtExceptionHandlerForTest != null) {
      Impl.uncaughtExceptionHandlerForTest.onUncaughtException(e);
    }

    UncaughtExceptionHandler handler = GWT.getUncaughtExceptionHandler();
    if (handler != null) {
      if (handler == Impl.uncaughtExceptionHandlerForTest) {
        return; // Already reported so we're done.
      }
      // TODO(goktug): Handler might throw an exception but catching and reporting it to browser
      // here breaks assumptions of some existing hybrid apps that uses UCE for exception
      // conversion. We don't have an alternative functionality (yet) and it is too risky to include
      // the change in the release at last minute.
      handler.onUncaughtException(e);
      return; // Done.
    }

    // Make sure that the exception is not swallowed
    if (GWT.isClient() && reportSwallowedExceptionToBrowser) {
      reportToBrowser(e);
    } else {
      System.err.print("Uncaught exception ");
      e.printStackTrace(System.err);
    }
  }

  private static void reportToBrowser(Throwable e) {
    reportToBrowser(e instanceof JavaScriptException ? ((JavaScriptException) e).getThrown() : e);
  }

  private static native void reportToBrowser(Object e) /*-{
    $wnd.setTimeout(function () {
      throw e;
    }, 0);
  }-*/;

  /**
   * Indicates if <code>$entry</code> has been called.
   */
  public static boolean isEntryOnStack() {
    return entryDepth > 0;
  }

  /**
   * Indicates if <code>$entry</code> is present on the stack more than once.
   */
  public static boolean isNestedEntry() {
    return entryDepth > 1;
  }

  /**
   * Implicitly called by JavaToJavaScriptCompiler.findEntryPoints().
   */
  public static native JavaScriptObject registerEntry() /*-{
    if (@com.google.gwt.core.client.GWT::isScript()()) {
      // Assignment to $entry is done by the compiler
      return @Impl::entry(*);
    } else {
      // But we have to do in in Development Mode
      return $entry = @Impl::entry(*);
    }
  }-*/;

  private static native Object apply(Object jsFunction, Object thisObj,
      Object args) /*-{
    if (@com.google.gwt.core.client.GWT::isScript()()) {
      return jsFunction.apply(thisObj, args);
    } else {
      var _ = jsFunction.apply(thisObj, args);
      if (_ != null) {
        // Wrap for Development Mode (unwrapped in #entry())
        _ = { val: _ };
      }
      return _;
    }
  }-*/;

  /**
   * Called by ModuleSpace in Development Mode when running onModuleLoads.
   */
  private static boolean enter() {
    assert entryDepth >= 0 : "Negative entryDepth value at entry " + entryDepth;

    if (GWT.isScript() && entryDepth != 0) {
      double now = Duration.currentTimeMillis();
      if (now - watchdogEntryDepthLastScheduled > WATCHDOG_ENTRY_DEPTH_CHECK_INTERVAL_MS) {
        watchdogEntryDepthLastScheduled = now;
        watchdogEntryDepthTimerId = watchdogEntryDepthSchedule();
      }
    }

    // We want to disable some actions in the reentrant case
    if (entryDepth++ == 0) {
      SchedulerImpl.INSTANCE.flushEntryCommands();
      return true;
    }
    return false;
  }

  /**
   * Implements {@link #entry(JavaScriptObject)}.
   */
  private static Object entry0(Object jsFunction, Object thisObj, Object args) throws Throwable {
    boolean initialEntry = enter();

    try {
      /*
       * Always invoke the UCE if we have one so that the exception never
       * percolates up to the browser's event loop, even in a reentrant
       * situation.
       */
      if (GWT.getUncaughtExceptionHandler() != null) {
        /*
         * This try block is guarded by the if statement so that we don't molest
         * the exception object traveling up the stack unless we're capable of
         * doing something useful with it.
         */
        try {
          return apply(jsFunction, thisObj, args);
        } catch (Throwable t) {
          reportUncaughtException(t);
          return undefined();
        }
      } else {
        // Can't handle any exceptions, let them percolate normally
        return apply(jsFunction, thisObj, args);
      }

      /*
       * DO NOT ADD catch(Throwable t) here, it would always wrap the thrown
       * value. Instead, entry() has a general catch-all block.
       */
    } finally {
      exit(initialEntry);
    }
  }

  /**
   * Called by ModuleSpace in Development Mode when running onModuleLoads.
   */
  private static void exit(boolean initialEntry) {
    if (initialEntry) {
      SchedulerImpl.INSTANCE.flushFinallyCommands();
    }

    // Decrement after we call flush
    entryDepth--;
    assert entryDepth >= 0 : "Negative entryDepth value at exit " + entryDepth;
    if (initialEntry) {
      assert entryDepth == 0 : "Depth not 0" + entryDepth;
      if (GWT.isScript() && watchdogEntryDepthTimerId != -1) {
        watchdogEntryDepthCancel(watchdogEntryDepthTimerId);
        watchdogEntryDepthTimerId = -1;
      }
    }
  }

  private static native Object undefined() /*-{
    // Intentionally not returning a value
    return;
  }-*/;

  private static native void watchdogEntryDepthCancel(int timerId) /*-{
    $wnd.clearTimeout(timerId);
  }-*/;

  private static void watchdogEntryDepthRun() {
    // Note: this must NEVER be called nested in a $entry() call.
    // This method is call from a "setTimeout": entryDepth should be set to 0.
    if (GWT.isScript() && entryDepth != 0) {
      entryDepth = 0;
    }
    watchdogEntryDepthTimerId = -1;  // Timer has run.
  }

  private static native int watchdogEntryDepthSchedule() /*-{
    return $wnd.setTimeout(@Impl::watchdogEntryDepthRun(), 10);
  }-*/;
}
