/*
  Copyright 2010 ZombieTuesday Ltd.

  Distributed under the terms of the GPL version 3.

  This program is free software: you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation, either version 3 of the License, or
  (at your option) any later version.
  
  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.
  
  For a copy of the GNU General Public License see <http://www.gnu.org/licenses/>.
 */

var running = new Array();
var halted = new Array();
var waiting = new Array();

var current = -1;

var cycletime = 10;
var lastStamp = -1;

var state;
var RUN = 1;
var HALT = 2;
var WAIT = 3;
var END = 4;
var waittime = -1;

function sched() {
  var stamp = new Date();

  // Check for waiting items to become ready...
  var newWaiting = new Array();
  while(waiting.length > 0) {
    var fundata = waiting.pop();
    fundata[0] = fundata[0] - (stamp - lastStamp);
    if(fundata[0] <= 0) {
      running.push(fundata[1]);
    } else {
      newWaiting.push(fundata);
    }
  }
  waiting = newWaiting;

  var newRunning = new Array();
  while(running.length > 0) {
    var fun = running.pop();
    fun();
    switch(state) {
    case RUN:
      newRunning.push(fun);
      break;
    case HALT:
      halted.push(fun);
      break;
    case WAIT:
      waiting.push(new Array(waittime, fun));
      break;
    case END:
      // Loose this pointer
      break;
    }
  }
  running = newRunning;

  lastStamp = stamp;
  setTimeout('sched()', cycletime);
}

setTimeout('sched()', cycletime);


// Halt the current process and return its id on the halt list for future restarts...
function halt() {
  state = HALT;
  return halted.length;
}

// Start the given item from the halted list
function start(id) {
  running.push(halted[id]);
  halted.splice(id, 1);
}

// Add the function to the wait queue
function wait(time) {
  waittime = time;
  state = WAIT;
}

function createThread(fun, state) {
  switch(state) {
  case HALT:
    halted.push(fun);
    return halted.length - 1;
  default:
    running.push(fun);
    return running.length - 1;
  }
}

function end() {
  state = END;
}

