/*
 * 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.Duration;
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.Scheduler;

/**
 * This is used by Scheduler to collaborate with Impl in order to have
 * FinallyCommands executed.
 */
public class SchedulerImpl extends Scheduler {
  /**
   * Metadata bag for command objects. It's a JSO so that a lightweight JsArray
   * can be used instead of a Collections type.
   */
  static final class Task extends JavaScriptObject {
    public static native Task create(RepeatingCommand cmd) /*-{
      return [cmd, true];
    }-*/;

    public static native Task create(ScheduledCommand cmd) /*-{
      return [cmd, false];
    }-*/;

    protected Task() {
    }

    public boolean executeRepeating() {
      return getRepeating().execute();
    }

    public void executeScheduled() {
      getScheduled().execute();
    }

    /**
     * Has implicit cast.
     */
    public native RepeatingCommand getRepeating() /*-{
      return this[0];
    }-*/;

    /**
     * Has implicit cast.
     */
    public native ScheduledCommand getScheduled() /*-{
      return this[0];
    }-*/;

    public native boolean isRepeating() /*-{
      return this[1];
    }-*/;
  }

  /**
   * Calls {@link SchedulerImpl#flushPostEventPumpCommands()}.
   */
  private final class Flusher implements RepeatingCommand {
    public boolean execute() {
      flushRunning = true;
      flushPostEventPumpCommands();
      /*
       * No finally here, we want this to be clear only on a normal exit. An
       * abnormal exit would indicate that an exception isn't being caught
       * correctly or that a slow script warning canceled the timer.
       */
      flushRunning = false;
      return shouldBeRunning = isWorkQueued();
    }
  }

  /**
   * Keeps {@link Flusher} running.
   */
  private final class Rescuer implements RepeatingCommand {
    public boolean execute() {
      if (flushRunning) {
        /*
         * Since JS is single-threaded, if we're here, then than means that
         * FLUSHER.execute() started, but did not finish. Reschedule FLUSHER.
         */
        scheduleFixedDelay(flusher, FLUSHER_DELAY);
      }
      return shouldBeRunning;
    }
  }

  /**
   * Use a GWT.create() here to make it simple to hijack the default
   * implementation.
   */
  public static final SchedulerImpl INSTANCE = GWT.create(SchedulerImpl.class);

  /**
   * The delay between flushing the task queues.
   */
  private static final int FLUSHER_DELAY = 1;

  /**
   * The delay between checking up on SSW problems.
   */
  private static final int RESCUE_DELAY = 50;

  /**
   * The amount of time that we're willing to spend executing
   * IncrementalCommands.
   */
  private static final double TIME_SLICE = 100;

  /**
   * Extract boilerplate code.
   */
  private static JsArray<Task> createQueue() {
    return JavaScriptObject.createArray().cast();
  }

  /**
   * Called from scheduledFixedInterval to give $entry a static function.
   */
  private static boolean execute(RepeatingCommand cmd) {
    return cmd.execute();
  }

  /**
   * Provides lazy-init pattern for the task queues.
   */
  private static JsArray<Task> push(JsArray<Task> queue, Task task) {
    if (queue == null) {
      queue = createQueue();
    }
    queue.push(task);
    return queue;
  }



  /**
   * Execute a list of Tasks that hold both ScheduledCommands and
   * RepeatingCommands. Any RepeatingCommands in the <code>tasks</code> queue
   * that want to repeat will be pushed onto the <code>rescheduled</code> queue.
   * The contents of <code>tasks</code> may not be altered while this method is
   * executing.
   * 
   * @return <code>rescheduled</code> or a newly-allocated array if
   *         <code>rescheduled</code> is null.
   */
  private static JsArray<Task> runScheduledTasks(JsArray<Task> tasks,
      JsArray<Task> rescheduled) {
    assert tasks != null : "tasks";

    for (int i = 0, j = tasks.length(); i < j; i++) {
      assert tasks.length() == j : "Working array length changed "
          + tasks.length() + " != " + j;
      Task t = tasks.get(i);

      try {
        // Move repeating commands to incremental commands queue
        if (t.isRepeating()) {
          if (t.executeRepeating()) {
            rescheduled = push(rescheduled, t);
          }
        } else {
          t.executeScheduled();
        }
      } catch (Throwable e) {
        if (GWT.getUncaughtExceptionHandler() != null) {
          GWT.getUncaughtExceptionHandler().onUncaughtException(e);
        }
      }
    }
    return rescheduled;
  }

  private static native void scheduleFixedDelayImpl(RepeatingCommand cmd,
      int delayMs) /*-{
    $wnd.setTimeout(function() {
      // $entry takes care of uncaught exception handling
      var ret = $entry(@com.google.gwt.core.client.impl.SchedulerImpl::execute(Lcom/google/gwt/core/client/Scheduler$RepeatingCommand;))(cmd);
      if (!@com.google.gwt.core.client.GWT::isScript()()) {
        // Unwrap from Development Mode
        ret = ret == true;
      }
      if (ret) {
        $wnd.setTimeout(arguments.callee, delayMs);
      }
    }, delayMs);
  }-*/;

  private static native void scheduleFixedPeriodImpl(RepeatingCommand cmd,
      int delayMs) /*-{
    var fn = function() {
      // $entry takes care of uncaught exception handling
      var ret = $entry(@com.google.gwt.core.client.impl.SchedulerImpl::execute(Lcom/google/gwt/core/client/Scheduler$RepeatingCommand;))(cmd);
      if (!@com.google.gwt.core.client.GWT::isScript()()) {
        // Unwrap from Development Mode
        ret = ret == true;
      }
      if (!ret) {
        // Either canceled or threw an exception
        $wnd.clearInterval(arguments.callee.token);
      }
    };
    fn.token = $wnd.setInterval(fn, delayMs);
  }-*/;

  /**
   * A RepeatingCommand that calls flushPostEventPumpCommands(). It repeats if
   * there are any outstanding deferred or incremental commands.
   */
  Flusher flusher;

  /**
   * This provides some backup for the main flusher task in case it gets shut
   * down by a slow-script warning.
   */
  Rescuer rescue;

  /*
   * Work queues. Timers store their state on the function, so we don't need to
   * track them. They are not final so that we don't have to shorten them.
   * Processing the values in the queues is a one-shot, and then the array is
   * discarded.
   */
  JsArray<Task> deferredCommands;
  JsArray<Task> entryCommands;
  JsArray<Task> finallyCommands;
  JsArray<Task> incrementalCommands;

  /*
   * These two flags are used to control the state of the flusher and rescuer
   * commands.
   */
  private boolean flushRunning = false;
  private boolean shouldBeRunning = false;

  /**
   * Called by {@link Impl#entry(JavaScriptObject)}.
   */
  public void flushEntryCommands() {
    if (entryCommands != null) {
      JsArray<Task> rescheduled = null;
      // This do-while loop handles commands scheduling commands
      do {
        JsArray<Task> oldQueue = entryCommands;
        entryCommands = null;
        rescheduled = runScheduledTasks(oldQueue, rescheduled);
      } while (entryCommands != null);
      entryCommands = rescheduled;
    }
  }

  /**
   * Called by {@link Impl#entry(JavaScriptObject)}.
   */
  public void flushFinallyCommands() {
    if (finallyCommands != null) {
      JsArray<Task> rescheduled = null;
      // This do-while loop handles commands scheduling commands
      do {
        JsArray<Task> oldQueue = finallyCommands;
        finallyCommands = null;
        rescheduled = runScheduledTasks(oldQueue, rescheduled);
      } while (finallyCommands != null);
      finallyCommands = rescheduled;
    }
  }

  @Override
  public void scheduleDeferred(ScheduledCommand cmd) {
    deferredCommands = push(deferredCommands, Task.create(cmd));
    maybeSchedulePostEventPumpCommands();
  }

  @Override
  public void scheduleEntry(RepeatingCommand cmd) {
    entryCommands = push(entryCommands, Task.create(cmd));
  }

  @Override
  public void scheduleEntry(ScheduledCommand cmd) {
    entryCommands = push(entryCommands, Task.create(cmd));
  }

  @Override
  public void scheduleFinally(RepeatingCommand cmd) {
    finallyCommands = push(finallyCommands, Task.create(cmd));
  }

  @Override
  public void scheduleFinally(ScheduledCommand cmd) {
    finallyCommands = push(finallyCommands, Task.create(cmd));
  }

  @Override
  public void scheduleFixedDelay(RepeatingCommand cmd, int delayMs) {
    scheduleFixedDelayImpl(cmd, delayMs);
  }

  @Override
  public void scheduleFixedPeriod(RepeatingCommand cmd, int delayMs) {
    scheduleFixedPeriodImpl(cmd, delayMs);
  }

  @Override
  public void scheduleIncremental(RepeatingCommand cmd) {
    // Push repeating commands onto the same initial queue for relative order
    deferredCommands = push(deferredCommands, Task.create(cmd));
    maybeSchedulePostEventPumpCommands();
  }

  /**
   * there for testing
   */
  Duration createDuration() {
    return new Duration();
  }

  /**
   * Called by Flusher.
   */
  void flushPostEventPumpCommands() {
    if (deferredCommands != null) {
      JsArray<Task> oldDeferred = deferredCommands;
      deferredCommands = null;

      /* We might not have any incremental commands queued. */
      if (incrementalCommands == null) {
        incrementalCommands = createQueue();
      }
      runScheduledTasks(oldDeferred, incrementalCommands);
    }

    if (incrementalCommands != null) {
      incrementalCommands = runRepeatingTasks(incrementalCommands);
    }
  }

  boolean isWorkQueued() {
    return deferredCommands != null || incrementalCommands != null;
  }

  private void maybeSchedulePostEventPumpCommands() {
    if (!shouldBeRunning) {
      shouldBeRunning = true;

      if (flusher == null) {
        flusher = new Flusher();
      }
      scheduleFixedDelayImpl(flusher, FLUSHER_DELAY);

      if (rescue == null) {
        rescue = new Rescuer();
      }
      scheduleFixedDelayImpl(rescue, RESCUE_DELAY);
    }
  }

  /**
   * Execute a list of Tasks that hold RepeatingCommands.
   *
   * @return A replacement array that is possibly a shorter copy of <code>tasks</code>
   */
  private JsArray<Task> runRepeatingTasks(JsArray<Task> tasks) {
    assert tasks != null : "tasks";

    int length = tasks.length();
    if (length == 0) {
      return null;
    }

    boolean canceledSomeTasks = false;

    Duration duration = createDuration();
    while (duration.elapsedMillis() < TIME_SLICE) {
      boolean executedSomeTask = false;
      for (int i = 0; i < length; i++) {
        assert tasks.length() == length : "Working array length changed " + tasks.length() + " != "
            + length;
        Task t = tasks.get(i);
        if (t == null) {
          continue;
        }
        executedSomeTask = true;

        assert t.isRepeating() : "Found a non-repeating Task";

        if (!t.executeRepeating()) {
          tasks.set(i, null);
          canceledSomeTasks = true;
        }
      }
      if (!executedSomeTask) {
        // no work left to do, break to avoid busy waiting until TIME_SLICE is reached
        break;
      }
    }

    if (canceledSomeTasks) {
      JsArray<Task> newTasks = createQueue();
      // Remove tombstones
      for (int i = 0; i < length; i++) {
        if (tasks.get(i) != null) {
          newTasks.push(tasks.get(i));
        }
      }
      assert newTasks.length() < length;
      return newTasks.length() == 0 ? null : newTasks;
    } else {
      return tasks;
    }
  }
}
