/*
 * Copyright 2011 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;

/*
 * Design note: This class intentionally does not use the GWT DOM wrappers so
 * that this code can pull in as few dependencies as possible and live in the
 * Core module.
 */

/**
 * Dynamically create a script tag and attach it to the DOM.
 * 
 * Usage with script as local string:
 * <p>
 * 
 * <pre>
 *   String scriptBody = "var foo = ...";
 *   ScriptInjector.fromString(scriptBody).inject();
 * </pre>
 * <p>
 * Usage with script loaded as URL:
 * <p>
 * 
 * <pre>
 *   ScriptInjector.fromUrl("http://example.com/foo.js").setCallback(
 *     new Callback<Void, Exception>() {
 *        public void onFailure(Exception reason) {
 *          Window.alert("Script load failed.");
 *        }
 *        public void onSuccess(Void result) {
 *          Window.alert("Script load success.");
 *        }
 *     }).inject();
 * </pre>
 * 
 * 
 */
public class ScriptInjector {

  /**
   * Builder for directly injecting a script body into the DOM.
   */
  public static class FromString {
    private boolean removeTag = true;
    private final String scriptBody;
    private JavaScriptObject window;

    /**
     * @param scriptBody The script text to install into the document.
     */
    public FromString(String scriptBody) {
      this.scriptBody = scriptBody;
    }

    /**
     * Injects a script into the DOM. The JavaScript is evaluated and will be
     * available immediately when this call returns.
     * 
     * By default, the script is installed in the same window that the GWT code
     * is installed in.
     * 
     * @return the script element created for the injection. Note that it may be
     *         removed from the DOM.
     */
    public JavaScriptObject inject() {
      JavaScriptObject wnd = (window == null) ? nativeDefaultWindow() : window;
      assert wnd != null;
      JavaScriptObject doc = nativeGetDocument(wnd);
      assert doc != null;
      JavaScriptObject scriptElement = nativeMakeScriptElement(doc);
      assert scriptElement != null;
      nativeSetText(scriptElement, scriptBody);
      nativePropagateScriptNonceIfPossible(doc, scriptElement);
      nativeAttachToHead(doc, scriptElement);
      if (removeTag) {
        nativeRemove(scriptElement);
      }
      return scriptElement;
    }

    /**
     * @param removeTag If true, remove the tag immediately after injecting the
     *          source. This shrinks the DOM, possibly at the expense of
     *          readability if you are debugging javaScript.
     * 
     *          Default value is {@code true}.
     */
    public FromString setRemoveTag(boolean removeTag) {
      this.removeTag = removeTag;
      return this;
    }

    /**
     * @param window Specify which window to use to install the script. If not
     *          specified, the top current window GWT is loaded in is used.
     */
    public FromString setWindow(JavaScriptObject window) {
      this.window = window;
      return this;
    }
  }

  /**
   * Build an injection call for adding a script by URL.
   */
  public static class FromUrl {
    private Callback<Void, Exception> callback;
    private boolean removeTag = false;
    private final String scriptUrl;
    private JavaScriptObject window;

    private FromUrl(String scriptUrl) {
      this.scriptUrl = scriptUrl;
    }

    /**
     * Injects an external JavaScript reference into the document and optionally
     * calls a callback when it finishes loading.
     * 
     * @return the script element created for the injection.
     */
    public JavaScriptObject inject() {
      JavaScriptObject wnd = (window == null) ? nativeDefaultWindow() : window;
      assert wnd != null;
      JavaScriptObject doc = nativeGetDocument(wnd);
      assert doc != null;
      JavaScriptObject scriptElement = nativeMakeScriptElement(doc);
      assert scriptElement != null;
      if (callback != null || removeTag) {
        attachListeners(scriptElement, callback, removeTag);
      }
      nativeSetSrc(scriptElement, scriptUrl);
      nativePropagateScriptNonceIfPossible(doc, scriptElement);
      nativeAttachToHead(doc, scriptElement);
      return scriptElement;
    }

    /**
     * Specify a callback to be invoked when the script is loaded or loading
     * encounters an error.
     * <p>
     * <b>Warning:</b> This class <b>does not</b> control whether or not a URL
     * has already been injected into the document. The client of this class has
     * the responsibility of keeping score of the injected JavaScript files.
     * <p>
     * <b>Known bugs:</b>  This class uses the script tag's <code>onerror()
     * </code> callback to attempt to invoke onFailure() if the 
     * browser detects a load failure.  This is not reliable on all browsers 
     * (Doesn't work on IE or Safari 3 or less).
     * <p>
     * On Safari version 3 and prior, the onSuccess() callback may be invoked
     * even when the load of a page fails.  
     * <p>
     * To support failure notification on IE and older browsers, you should 
     * check some side effect of the script (such as a defined function)
     * to see if loading the script worked and include timeout logic.
     * 
     * @param callback callback that gets invoked asynchronously.
     */
    public FromUrl setCallback(Callback<Void, Exception> callback) {
      this.callback = callback;
      return this;
    }

    /**
     * @param removeTag If true, remove the tag after the script finishes
     *          loading. This shrinks the DOM, possibly at the expense of
     *          readability if you are debugging javaScript.
     *
     *          Default value is {@code false}, but this may change in a future
     *          release.
     */
    public FromUrl setRemoveTag(boolean removeTag) {
      this.removeTag = removeTag;
      return this;
    }

    /**
     * This call allows you to specify which DOM window object to install the
     * script tag in. To install into the Top level window call
     * 
     * <code>
     *   builder.setWindow(ScriptInjector.TOP_WINDOW);
     * </code>
     * 
     * @param window Specifies which window to install in.
     */
    public FromUrl setWindow(JavaScriptObject window) {
      this.window = window;
      return this;
    }
  }

  /**
   * Returns the top level window object. Use this to inject a script so that
   * global variable references are available under <code>$wnd</code> in JSNI
   * access.
   * <p>
   * Note that if your GWT app is loaded from a different domain than the top
   * window, you may not be able to add a script element to the top window.
   */
  public static final JavaScriptObject TOP_WINDOW = nativeTopWindow();

  /**
   * Build an injection call for directly setting the script text in the DOM.
   * 
   * @param scriptBody the script text to be injected and immediately executed.
   */
  public static FromString fromString(String scriptBody) {
    return new FromString(scriptBody);
  }

  /**
   * Build an injection call for adding a script by URL.
   * 
   * @param scriptUrl URL of the JavaScript to be injected.
   */
  public static FromUrl fromUrl(String scriptUrl) {
    return new FromUrl(scriptUrl);
  }

  /**
   * Attaches event handlers to a script DOM element that will run just once a
   * callback when it gets successfully loaded.
   * <p>
   * <b>IE Notes:</b> Internet Explorer calls {@code onreadystatechanged}
   * several times while varying the {@code readyState} property: in theory,
   * {@code "complete"} means the content is loaded, parsed and ready to be
   * used, but in practice, {@code "complete"} happens when the JS file was
   * already cached, and {@code "loaded"} happens when it was transferred over
   * the network. Other browsers just call the {@code onload} event handler. To
   * ensure the callback will be called at most once, we clear out both event
   * handlers when the callback runs for the first time. More info at the <a
   * href="http://www.phpied.com/javascript-include-ready-onload/">phpied.com
   * blog</a>.
   * <p>
   * In IE, do not trust the "order" of {@code readyState} values. For instance,
   * in IE 8 running in Vista, if the JS file is cached, only {@code "complete"}
   * will happen, but if the file has to be downloaded, {@code "loaded"} can
   * fire in parallel with {@code "loading"}.
   * 
   * 
   * @param scriptElement element to which the event handlers will be attached
   * @param callback callback that runs when the script is loaded and parsed.
   */
  private static native void attachListeners(JavaScriptObject scriptElement,
      Callback<Void, Exception> callback, boolean removeTag) /*-{
    function clearCallbacks() {
      scriptElement.onerror = scriptElement.onreadystatechange = scriptElement.onload = null;
      if (removeTag) {
        @com.google.gwt.core.client.ScriptInjector::nativeRemove(Lcom/google/gwt/core/client/JavaScriptObject;)(scriptElement);
      }
    }
    scriptElement.onload = $entry(function() {
      clearCallbacks();
      if (callback) {
        callback.@com.google.gwt.core.client.Callback::onSuccess(Ljava/lang/Object;)(null);
      }
    });
    // or possibly more portable script_tag.addEventListener('error', function(){...}, true);
    scriptElement.onerror = $entry(function() {
      clearCallbacks();
      if (callback) {
        var ex = @com.google.gwt.core.client.CodeDownloadException::new(Ljava/lang/String;)("onerror() called.");
        callback.@com.google.gwt.core.client.Callback::onFailure(Ljava/lang/Object;)(ex);
      }
    });
    scriptElement.onreadystatechange = $entry(function() {
      if (/loaded|complete/.test(scriptElement.readyState)) {
        scriptElement.onload();
      }
    });
  }-*/;

  private static native void nativeAttachToHead(JavaScriptObject doc, JavaScriptObject scriptElement) /*-{
    // IE8 does not have document.head
    (doc.head || doc.getElementsByTagName("head")[0]).appendChild(scriptElement);
  }-*/;

  private static native JavaScriptObject nativeDefaultWindow() /*-{
    return window;
  }-*/;

  private static native JavaScriptObject nativeGetDocument(JavaScriptObject wnd) /*-{
    return wnd.document;
  }-*/;

  private static native JavaScriptObject nativeMakeScriptElement(JavaScriptObject doc) /*-{
    return doc.createElement("script");
  }-*/;

  private static native void nativeRemove(JavaScriptObject scriptElement) /*-{
    scriptElement.parentNode.removeChild(scriptElement);
  }-*/;

  private static native void nativeSetSrc(JavaScriptObject element, String url) /*-{
    element.src = url;
  }-*/;

  private static native void nativeSetText(JavaScriptObject element, String scriptBody) /*-{
    element.text = scriptBody;
  }-*/;

  private static native void nativePropagateScriptNonceIfPossible(
      JavaScriptObject doc, JavaScriptObject element) /*-{
    if (doc.querySelector && doc.querySelector('script[nonce]')) {
      var firstNoncedScript = doc.querySelector('script[nonce]');
      var nonce = firstNoncedScript['nonce'] || firstNoncedScript.getAttribute('nonce');
      element.setAttribute('nonce', nonce);
    }
  }-*/;

  private static native JavaScriptObject nativeTopWindow() /*-{
    return $wnd;
  }-*/;

  /**
   * Utility class - do not instantiate
   */
  private ScriptInjector() {
  }
}
