/*
 * 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.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 {

  public static boolean moduleUnloaded = false;

  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;
  private static int sNextHashId = 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;

  private static UnloadSupport unloadSupport = GWT.isScript() ?
      (UnloadSupport) GWT.create(UnloadSupport.class) : new UnloadSupport();

  static {
     exportUnloadModule();
  }

  public static void clearInterval(int timerId) {
    unloadSupport.clearInterval(timerId);
  }

  public static void clearTimeout(int timerId) {
    unloadSupport.clearTimeout(timerId);
  }

  public static void dispose(Disposable d) {
    unloadSupport.dispose(d);
  }

  /**
   * 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() {
      try {
        return @com.google.gwt.core.client.impl.Impl::entry0(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)(jsFunction, this, arguments);
      } catch (e) {
        // This catch block is here to ensure that the finally block in entry0
        // will be executed correctly on IE6/7.  We can't put a catch Throwable
        // in entry0 because this would always cause the unhandled exception to
        // be wrapped in a JavaScriptException type.
        throw e;
      }
    };
  }-*/;

  public static void exportUnloadModule() {
    unloadSupport.exportUnloadModule();
  }

  /**
   * Gets an identity-based hash code on the passed-in Object by adding an
   * expando. This method should not be used with <code>null</code> or any
   * String. The former will crash and the later will produce unstable results
   * when called repeatedly with a String primitive.
   * <p>
   * The sequence of hashcodes generated by this method are a
   * monotonically-increasing sequence.
   */
  public static native int getHashCode(Object o) /*-{
    return o.$H || (o.$H = @com.google.gwt.core.client.impl.Impl::getNextHashId()());
  }-*/;

  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.
   *
   * @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.
   * @see com.google.gwt.core.client.impl.ArtificialRescue
   */
  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;
  }

  public static void reportUncaughtException(Throwable e) {
    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 and let the browser handle it
    reportToBrowser(e);
  }

  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;
  }

  public static boolean isModuleUnloaded() {
    return moduleUnloaded;
  }

  /**
   * 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 @com.google.gwt.core.client.impl.Impl::entry(Lcom/google/gwt/core/client/JavaScriptObject;);
    } else {
      // But we have to do in in Development Mode
      return $entry = @com.google.gwt.core.client.impl.Impl::entry(Lcom/google/gwt/core/client/JavaScriptObject;);
    }
  }-*/;

  public static void scheduleDispose(Disposable d) {
    unloadSupport.scheduleDispose(d);
  }

  public static int setInterval(JavaScriptObject func, int time) {
    return unloadSupport.setInterval(func, time);
  }

  public static int setTimeout(JavaScriptObject func, int time) {
    return unloadSupport.setTimeout(func, time);
  }

  public static void unloadModule() {
    if (unloadSupport.isUnloadSupported()) {
      moduleUnloaded = true;
      unloadSupport.disposeAll();
    }
  }

  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
        _ = Object(_);
      }
      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 {
    // if module is unloaded, don't run anything
    if (unloadSupport.isUnloadSupported() && Impl.isModuleUnloaded()) {
      return null;
    }
    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;
      }
    }
  }

  /**
   * Called from JSNI. Do not change this implementation without updating:
   * <ul>
   * <li>{@link com.google.gwt.user.client.rpc.impl.SerializerBase}</li>
   * </ul>
   */
  private static int getNextHashId() {
    return ++sNextHashId;
  }

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

  private static native void watchdogEntryDepthCancel(int timerId) /*-{
    @com.google.gwt.core.client.impl.Impl::clearTimeout(I)(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 @com.google.gwt.core.client.impl.Impl::setTimeout(Lcom/google/gwt/core/client/JavaScriptObject;I)(function() {
      @com.google.gwt.core.client.impl.Impl::watchdogEntryDepthRun()();
    }, 10);
  }-*/;
}
