/* Timer class for Mootools.
 * Released under the GPLv3 license to the Mootools project.  I don't really
 * care which license, as long as it stays free and Free and is otherwise
 * shareable.  GPLv3 is the mechanism that I choose for that.
 *
 *     Options currently implemented:
 * length - in milliseconds, how long to set the timer
 * granularity - in milliseconds, how often to update display
 * callback - function, will be called when timer hits zero
 * display - will replace innerHTML of this element.
 *
 *     Functions currently implemented:
 * void setTimer ( num[int] ) - Set the timer to any length, in milliseconds.
 *    NB: does not update a running timer.  To update a timer, you must stop and
 *    restart it.
 * void startTimer () - Start the timer.
 * void stopTimer ()  - Stop the timer.
 * void setDisplay ( obj ) - obj.innerHTML will be automatically updated with
 *    time display.
 * int elapsedTime () - Returns the time in seconds since timer started.
 * str display ( secs[int], tenths[bool] ) - Returns secs converted to hh:mm:ss
 *    format, optionally with tenths.
 */

var Timer = new Class({
	Implements: [Options],
	options: {
		length:      5000, // in milliseconds, how long to time.
		granularity:  250, // in milliseconds, how often to update display.
		callback:    null, // What to do when timer completes
		display:     null  // so timer can update in place
	},
	initialize: function (options) {
		this.setOptions( options );
		this.data = new Object();
	},
	setTimer: function ( secs ) { this.options.length = Math.abs( length, 0 ); },
	startTimer: function ( ) {
		this.data.startTime = (new Date()).getTime();
		this.data.endTime   = this.data.startTime + this.options.length;
		this.data.isRunning = true;
		this.updateTimer();
	},
	stopTimer: function ( ) {
		this.data.isRunning = false;
		this.updateTimer();
	},
	setDisplay: function ( obj ) {
		this.data.obj = obj;
		if ( null != obj )
			this.data.obj.innerHTML = this.display( length );
	},
	elapsedTime: function ( ) {
		return( (new Date()).getTime() - this.data.startTime );
	},
	updateTimer: function ( ) {
		var length = Math.max( this.data.endTime - (new Date()).getTime(), 0 );

		if ( ! (length > 0) ) {
			this.data.isRunning = false;
			if (this.options.callback)
				this.options.callback();
			return;
		}
		if ( this.data.isRunning ) {
			var updateIn = Math.min( length, this.options.granularity );
			this.updateTimer.delay( updateIn, this );
		}
		if ( this.data.obj )
			this.data.obj.innerHTML = this.display( length );
	},
	display: function ( time, tenths ) {
		time = parseInt(time/100); // for now, only deal with tenths of seconds
		var t = time % 10;  time = parseInt(time/10); // tenths of a second
		var s = time % 60;  time = parseInt(time/60); // seconds
		var m = time % 60;  time = parseInt(time/60); // minutes
		var h = time;

		var str = this.prettify_num(s);
		if ( tenths )
			str += '.' + t;

		return( str );
	},
	prettify_num: function ( n ) {
		if ( n < 10 )
			n = '0' + n;
		return( n );
	}
});