/*
 * 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.GWT;
import com.google.gwt.core.client.JavaScriptObject;

/**
 * <p>
 * Low-level support to download an extra fragment of code. This should not be
 * invoked directly by user code.
 * </p>
 * 
 * <p>
 * The fragments are numbered as follows, assuming there are <em>m</em> split
 * points:
 * 
 * <ul>
 * <li>0 -- the <em>base</em> fragment, which is initially downloaded
 * <li>1..m -- fragments for each split point
 * <li>m+1 -- the <em>leftovers</em> fragment of code that goes nowhere else
 * </ul>
 * 
 * <p>
 * Since the precise way to load code depends on the linker, linkers should
 * specify a rebind of {@link LoadingStrategy}.  The default rebind is
 * {@link XhrLoadingStrategy}.
 */
public class AsyncFragmentLoader {
  /**
   * An interface for handlers of load completion.  On a failed download,
   * this callback should be invoked or else the requested download will
   * hang indefinitely.  On a successful download, it's optional to call
   * this method.  If it is called at all, it must be called after
   * the downloaded code has been installed, so that {@link AsyncFragmentLoader}
   * can distinguish successful from unsuccessful downloads.
   */
  public static interface LoadTerminatedHandler {
    void loadTerminated(Throwable reason);
  }

  /**
   * A strategy for loading code fragments.
   */
  public interface LoadingStrategy {
    void startLoadingFragment(int fragment,
        LoadTerminatedHandler loadTerminatedHandler);
  }

  /**
   * A strategy for logging progress.
   */
  public interface Logger {
    /**
     * Log an event. The <code>fragment</code> and <code>size</code> are boxed
     * so that they can be optional. A value of <code>null</code> for either one
     * means that they are not specified.
     */
    void logEventProgress(String eventGroup, String type, int fragment,
        int size);
  }

  /**
   * Labels used for runAsync lightweight metrics.
   */
  public static class LwmLabels {
    public static final String BEGIN = "begin";

    public static final String END = "end";

    private static final String LEFTOVERS_DOWNLOAD = "leftoversDownload";

    private static String downloadGroupForExclusive(int splitPoint) {
      return "download" + splitPoint;
    }
  }

  /**
   * The standard logger used in a web browser. It uses the lightweight metrics
   * system.
   */
  public static class StandardLogger implements Logger {
    /**
     * Always use this as {@link isStatsAvailable} &amp;&amp;
     * {@link #stats(JavaScriptObject)}.
     */
    private static native boolean stats(JavaScriptObject data) /*-{
      return $stats(data);
    }-*/;

    public void logEventProgress(String eventGroup, String type,
        int fragment, int size) {
      @SuppressWarnings("unused")
      boolean toss = isStatsAvailable()
          && stats(createStatsEvent(eventGroup, type, fragment, size));
    }

    private native JavaScriptObject createStatsEvent(String eventGroup,
        String type, int fragment, int size) /*-{
      var evt = {
       moduleName: @com.google.gwt.core.client.GWT::getModuleName()(), 
        sessionId: $sessionId,
        subSystem: 'runAsync',
        evtGroup: eventGroup,
        millis: (new Date()).getTime(),
        type: type
      };
      if (fragment >= 0) {
        evt.fragment = fragment;
      }
      if (size >= 0) {
        evt.size = size;
      }
      return evt;
    }-*/;

    private native boolean isStatsAvailable() /*-{
      return !!$stats;
    }-*/;
  }

  /**
   * An exception indicating than at HTTP download failed.
   */
  static class HttpDownloadFailure extends RuntimeException {
    private final int statusCode;

    public HttpDownloadFailure(String url, int statusCode, String statusText) {
      super("Download of " + url + " failed with status " + statusCode + "("
          + statusText + ")");
      this.statusCode = statusCode;
    }

    public int getStatusCode() {
      return statusCode;
    }
  }

  /**
   * An exception indicating than at HTTP download succeeded, but installing
   * its body failed.
   */
  static class HttpInstallFailure extends RuntimeException {
    public HttpInstallFailure(String url, String text, Throwable rootCause) {
      super("Install of " + url + " failed with text " + text, rootCause);
    }
  }

  /**
   * A trivial queue of int's that should compile much better than a
   * LinkedList&lt;Integer&gt;. It assumes that it has a bound on the number of
   * items added to the queue. Removing items does not free up more space, but
   * calling <code>clear()</code> does.
   */
  private static class BoundedIntQueue {
    private final int[] array;
    private int read = 0;
    private int write = 0;

    public BoundedIntQueue(int maxPuts) {
      array = new int[maxPuts];
    }

    public void add(int x) {
      assert (write < array.length);
      array[write++] = x;
    }

    /**
     * Removes all elements, and also makes all space in the queue available
     * again.
     */
    public void clear() {
      read = 0;
      write = 0;
    }

    public int peek() {
      assert read < write;
      return array[read];
    }

    public int remove() {
      assert read < write;
      return array[read++];
    }

    public int size() {
      return write - read;
    }
  }

  /**
   * Internal load error handler. This calls all user-provided error handlers
   * and cancels all pending downloads.
   */
  private class ResetAfterDownloadFailure implements LoadTerminatedHandler {
    private final int fragment;
    
    public ResetAfterDownloadFailure(int myFragment) {
      this.fragment = myFragment;
    }

    public void loadTerminated(Throwable reason) {
      if (fragmentLoading != fragment) {
        // fragment already loaded successfully
        return;
      }

      // Cancel all pending downloads.

      /*
       * Make a local list of the handlers to run, in case one of them calls
       * another runAsync
       */
      LoadTerminatedHandler[] handlersToRun = pendingDownloadErrorHandlers;
      pendingDownloadErrorHandlers = new LoadTerminatedHandler[numEntries + 1];

      /*
       * Call clear() here so that requestedExclusives makes all of its space
       * available for later requests.
       */
      requestedExclusives.clear();

      fragmentLoading = -1;

      /*
       * Run the handlers. If an exception is thrown while canceling any of
       * them, remember and throw the last one.
       */
      RuntimeException lastException = null;

      for (LoadTerminatedHandler handler : handlersToRun) {
        if (handler != null) {
          try {
            handler.loadTerminated(reason);
          } catch (RuntimeException e) {
            lastException = e;
          }
        }
      }

      if (lastException != null) {
        throw lastException;
      }
    }
  }

  /**
   * The standard instance of AsyncFragmentLoader used in a web browser.  If
   * not in GWT (i.e our vanilla JUnit tests, or if referenced in a server
   * context), this filed is {@code null}.  In GWT, the parameters to this call
   * are rewritten by {@link com.google.gwt.dev.jjs.impl.ReplaceRunAsyncs}.  So
   * this must be a method call of exactly two arguments, or that magic fails.
   */
  public static AsyncFragmentLoader BROWSER_LOADER =
    makeBrowserLoader(1, new int[] {});
  
  /**
   * A helper static method that invokes
   * BROWSER_LOADER.leftoversFragmentHasLoaded(). Such a call is generated by
   * the compiler, as it is much simpler if there is a static method to wrap up
   * the call.
   */
  public static void browserLoaderLeftoversFragmentHasLoaded() {
    BROWSER_LOADER.leftoversFragmentHasLoaded();
  }

  /**
   * Creates the loader stored as {@link #BROWSER_LOADER}.
   * @returns {@code null} if not in GWT client code, where
   *   {@link GWT#create(Class)} cannot be used, or a fragment loader for
   *   the user's application otherwise.
   */
  private static AsyncFragmentLoader makeBrowserLoader(int numFragments,
      int initialLoad[]) {
    if (GWT.isClient()) {
      return new AsyncFragmentLoader(numFragments, initialLoad,
          (LoadingStrategy) GWT.create(LoadingStrategy.class),
          (Logger) GWT.create(Logger.class));
    } else {
      return null;
    }
  }

  /**
   * The fragment currently loading, or -1 if there aren't any.
   */
  private int fragmentLoading = -1;

  /**
   * The sequence of fragments to load initially, before anything else can be
   * loaded. This array will hold the initial sequence of bases followed by the
   * leftovers fragment. It is filled in by
   * {@link com.google.gwt.dev.jjs.impl.CodeSplitter} modifying the initializer
   * to {@link #BROWSER_LOADER}. The list does <em>not</em> include the leftovers
   * fragment, which must be loaded once all of these are finished.
   */
  private final int[] initialLoadSequence;

  /**
   * This array indicates which fragments have been successfully loaded.
   */
  private final boolean[] isLoaded;

  private final LoadingStrategy loadingStrategy;

  private final Logger logger;

  /**
   * The total number of entry points in the program, which is the number of
   * split points plus one for the main entry point of the program.
   */
  private final int numEntries;

  /**
   * Externally provided handlers for all outstanding and queued download
   * requests.
   */
  private LoadTerminatedHandler[] pendingDownloadErrorHandlers;

  /**
   * Whether prefetching is currently enabled.
   */
  private boolean prefetching = false;

  /**
   * This queue has fragments that have been requested to be prefetched. If it's
   * <code>null</code>, that indicates no prefetch requests, which should cause
   * all of this class's prefetching code to drop out of the compiled output.
   */
  private BoundedIntQueue prefetchQueue = null;

  /**
   * Base fragments that remain to be downloaded. It is lazily initialized in
   * the first call to {@link #startLoadingNextFragment()}. It does include the
   * leftovers fragment.
   */
  private BoundedIntQueue remainingInitialFragments = null;

  /**
   * Exclusive fragments that have been requested but that are not yet
   * downloading.
   */
  private final BoundedIntQueue requestedExclusives;

  public AsyncFragmentLoader(int numEntries, int[] initialLoadSequence,
      LoadingStrategy loadingStrategy, Logger logger) {
    this.numEntries = numEntries;
    this.initialLoadSequence = initialLoadSequence;
    this.loadingStrategy = loadingStrategy;
    this.logger = logger;
    int numEntriesPlusOne = numEntries + 1;
    requestedExclusives = new BoundedIntQueue(numEntriesPlusOne);
    isLoaded = new boolean[numEntriesPlusOne];
    pendingDownloadErrorHandlers = new LoadTerminatedHandler[numEntriesPlusOne];
  }

  /**
   * Inform the loader that a fragment has now finished loading.
   */
  public void fragmentHasLoaded(int fragment) {
    logFragmentLoaded(fragment);
    if (fragment < pendingDownloadErrorHandlers.length) {
      pendingDownloadErrorHandlers[fragment] = null;
    }

    if (isInitial(fragment)) {
      assert (fragment == remainingInitialFragments.peek());
      remainingInitialFragments.remove();
    }

    assert (fragment == fragmentLoading);
    fragmentLoading = -1;

    assert !isLoaded[fragment];
    isLoaded[fragment] = true;

    startLoadingNextFragment();
  }

  /**
   * Requests a load of the code for the specified split point. If the load
   * fails, <code>loadErrorHandler</code> will be invoked. If it succeeds, then
   * the code will be installed, and the code is expected to invoke its own
   * on-success hooks, including a call to either
   * {@link #leftoversFragmentHasLoaded()} or {@link #fragmentHasLoaded(int)}.
   * 
   * @param splitPoint the split point whose code needs to be loaded
   */
  public void inject(int splitPoint, LoadTerminatedHandler loadErrorHandler) {
    pendingDownloadErrorHandlers[splitPoint] = loadErrorHandler;
    if (!isInitial(splitPoint)) {
      requestedExclusives.add(splitPoint);
    }
    startLoadingNextFragment();
  }

  public boolean isAlreadyLoaded(int splitPoint) {
   return isLoaded[splitPoint];
  }

  public boolean isLoading(int splitPoint) {
    return pendingDownloadErrorHandlers[splitPoint] != null;
  }

  public void leftoversFragmentHasLoaded() {
    fragmentHasLoaded(leftoversFragment());
  }

  /**
   * Log an event with the {@Logger} this instance was provided.
   */
  public void logEventProgress(String eventGroup, String type) {
    logEventProgress(eventGroup, type, -1, -1);
  }

  /**
   * Request that a sequence of split points be prefetched. Code for the split
   * points in <code>splitPoints</code> will be downloaded and installed
   * whenever there is nothing else to download. Each call to this method
   * overwrites the entire prefetch queue with the newly specified one.
   */
  public void setPrefetchQueue(int... runAsyncSplitPoints) {
    if (prefetchQueue == null) {
      prefetchQueue = new BoundedIntQueue(numEntries);
    }
    prefetchQueue.clear();
    for (int sp : runAsyncSplitPoints) {
      prefetchQueue.add(sp);
    }
    startLoadingNextFragment();
  }

  public void startPrefetching() {
    prefetching = true;
    startLoadingNextFragment();
  }

  public void stopPrefetching() {
    prefetching = false;
  }

  private boolean anyPrefetchesRequested() {
    return prefetching && prefetchQueue != null && prefetchQueue.size() > 0;
  }

  /**
   * Clear out any inject and prefetch requests that are already loaded. Only
   * remove items from the head of each queue; any stale entries later in the
   * queue will be removed later.
   */
  private void clearRequestsAlreadyLoaded() {
    while (requestedExclusives.size() > 0
        && isLoaded[requestedExclusives.peek()]) {
      int offset = requestedExclusives.remove();
      if (offset < pendingDownloadErrorHandlers.length) {
        pendingDownloadErrorHandlers[offset] = null;
      }
    }

    if (prefetchQueue != null) {
      while (prefetchQueue.size() > 0 && isLoaded[prefetchQueue.peek()]) {
        prefetchQueue.remove();
      }
    }
  }

  private String downloadGroup(int fragment) {
    return (fragment == leftoversFragment()) ? LwmLabels.LEFTOVERS_DOWNLOAD
        : LwmLabels.downloadGroupForExclusive(fragment);
  }

  /**
   * Return whether all initial fragments have completed loading.
   */
  private boolean haveInitialFragmentsLoaded() {
    return remainingInitialFragments != null
        && remainingInitialFragments.size() == 0;
  }

  /**
   * Initialize {@link #remainingInitialFragments} if it isn't already.
   */
  private void initializeRemainingInitialFragments() {
    if (remainingInitialFragments == null) {
      remainingInitialFragments = new BoundedIntQueue(
          initialLoadSequence.length + 1);
      for (int sp : initialLoadSequence) {
        remainingInitialFragments.add(sp);
      }
      remainingInitialFragments.add(leftoversFragment());
    }
  }

  /**
   * Returns <code>true</code> if array contains only <code>null</code>
   * elements.
   */
  private boolean isEmpty(Object[] array) {
    for (int i = 0; i < array.length; i++) {
      if (array[i] != null) {
        return false;
      }
    }
    return true;
  }

  private boolean isInitial(int splitPoint) {
    if (splitPoint == leftoversFragment()) {
      return true;
    }
    for (int sp : initialLoadSequence) {
      if (sp == splitPoint) {
        return true;
      }
    }
    return false;
  }

  private int leftoversFragment() {
    return numEntries;
  }

  private void logDownloadStart(int fragment) {
    logEventProgress(downloadGroup(fragment), LwmLabels.BEGIN, fragment, -1);
  }

  /**
   * Log event progress via the {@link Logger} this instance was provided. The
   * <code>fragment</code> and <code>size</code> objects are allowed to be
   * <code>null</code>.
   */
  private void logEventProgress(String eventGroup, String type, int fragment,
      int size) {
    logger.logEventProgress(eventGroup, type, fragment, size);
  }

  private void logFragmentLoaded(int fragment) {
    String logGroup = downloadGroup(fragment);
    logEventProgress(logGroup, LwmLabels.END, fragment, -1);
  }

  private void startLoadingFragment(int fragment) {
    assert (fragmentLoading < 0);
    fragmentLoading = fragment;
    logDownloadStart(fragment);
    loadingStrategy.startLoadingFragment(fragment,
        new ResetAfterDownloadFailure(fragment));
  }

  /**
   * Start downloading the next fragment queued up, if there are any.
   */
  private void startLoadingNextFragment() {
    if (fragmentLoading >= 0) {
      // Already loading something
      return;
    }

    initializeRemainingInitialFragments();
    clearRequestsAlreadyLoaded();

    if (isEmpty(pendingDownloadErrorHandlers) && !anyPrefetchesRequested()) {
      /*
       * Don't load anything if there aren't any requests outstanding.
       */
      return;
    }

    // Check if an initial needs downloading
    if (remainingInitialFragments.size() > 0) {
      startLoadingFragment(remainingInitialFragments.peek());
      return;
    }

    assert (haveInitialFragmentsLoaded());

    // Check if an exclusive is pending
    if (requestedExclusives.size() > 0) {
      startLoadingFragment(requestedExclusives.remove());
      return;
    }

    // Check the prefetch queue
    if (anyPrefetchesRequested()) {
      startLoadingFragment(prefetchQueue.remove());
      return;
    }

    // Nothing needed downloading after all?!
    assert false;
  }
}
