/**
 * @class This class represents a timer service to control the execution of recurring tasks
 * that should always be executed after a certain amount of time has passed since the last execution
 * or to delay code execution.
 * @package rebox.service
 * @extends ServiceBase
 * @author Peter Payerl
 * @version 1.00
 */
function Timer() {
	var me = this;
	var myCounter = 1;
	var myTimer = new Array();
	
	
	/* ********************************************************* */
	/*                        CREATION                           */
	/* ********************************************************* */
	
	me.stop = function() {
		// stop all intervals and timeouts when the service is about to shut down
		for(var key in myTimer) {
			window.clearInterval(myTimer[key].timer);
			window.clearTimeout(myTimer[key].timer);
		}
	}
	
	
	/* ********************************************************* */
	/*                        FUNCTIONS                          */
	/* ********************************************************* */
	
	/**
	 * Starts a new timer and calls it periodically.
	 * @example System.getService("Timer").startTimer(100, null, onTimer, "Peter", 34);
	 * @param {integer} inInterval the time between each call in milliseconds
	 * @param {integer} [inNumber] the number of times the timer should be called, null if infinte
	 * @param {method} inHandler the method to call
	 * @param {any} inParameters... an arbitrary number of parameters that are passed to the method on every call
	 * @return {integer} an unique ID that can be used to stop the timer at a later timer
	 * @version 1.00
	 */
	me.startTimer = function(inInterval, inNumber, inCallback, inHandler) {
		inNumber = inNumber ? inNumber : -1;
		
		// create a timer object
		var timer = new Object();
		timer.handler = inHandler;
		timer.counter = inNumber;
		timer.callback = inCallback;
		timer.parameter = new Array();
		for(var i=4; i<arguments.length; i++) {
			timer.parameter[i-4] = arguments[i];
		}
		// set javascript timer
		timer.timer = window.setInterval("Timer.onTimerInternal('" + myCounter + "')", inInterval);
		
		// store timer object
		myTimer[myCounter] = timer;
		return myCounter++;
	}
	
	/**
	 * Stops the timer with the given ID.
	 * @param {integer} inTimer the unique ID of the timer to stop
	 * @version 1.00
	 */
	me.stopTimer = function(inTimer) {
		window.clearInterval(myTimer[inTimer].timer);
		delete myTimer[inTimer];
	}
	
	/**
	 * Starts a new timeout, which is a single call to the specified method once the given period of time has passed.
	 * @example System.getService("Timer").startTimeout(100, onTimeout, "Peter", 34);
	 * @param {integer} inDelay the time after which the method should be called in milliseconds
	 * @param {method} inHandler the method to call
	 * @param {any} inParameters... an arbitrary number of parameters that are passed to the method
	 * @return {integer} an unique ID that can be used to stop the timeout before execution
	 * @version 1.00
	 */
	me.startTimeout = function(inInterval, inHandler) {
		// create a timer object
		var timer = new Object();
		timer.handler = inHandler;
		timer.parameter = new Array();
		for(var i=2; i<arguments.length; i++) {
			timer.parameter[i-2] = arguments[i];
		}
		// set javascript timeout
		timer.timer = window.setTimeout("Timer.onTimerInternal('" + myCounter + "')", inInterval);
		
		// store timer object
		myTimer[myCounter] = timer;
		return myCounter++;
	}
	
	/**
	 * Stops the timeout with the given ID.
	 * @param {integer} inTimer the unique ID of the timeout to stop
	 * @version 1.00
	 */
	me.stopTimeout = function(inTimer) {
		window.clearTimeout(myTimer[inTimer].timer);
		delete myTimer[inTimer];
	}
	
	
	/* ********************************************************* */
	/*                      INTERNAL EVENTS                      */
	/* ********************************************************* */
	
	/**
	 * description
	 * @param {integer} inIndex description
	 * @version 1.00
	 * @private
	 */
	me.onTimerInternal = function(inTimer) {
		var timer = myTimer[inTimer];
		
		if(timer.handler) {
			// create handler signature and call it
			var signature = "timer.handler.call(this";
			for(var i=0; i<timer.parameter.length; i++) {
				signature = signature + ", timer.parameter[" + i + "]";
			}
			eval(signature + ")");
			
			if(timer.counter) timer.counter = timer.counter-1;
			if(timer.counter == 0) {
				me.stopTimer(inTimer);
				timer.callback.call(this);
			}
		} else {
			// stop current timer if the specified handler does no longer exist
			if(timer.counter != null) me.stopTimer(inTimer);
		}
		
		// remove handled timeouts from the pool of running timer in any case
		if(timer.counter == null) delete myTimer[inTimer];
	}
}
