﻿// JavaScript Document
// simple timer helper functions
// code by Azer Manafov (azerman[at]hotmail[dot]com)
var TIMER_DELAY 	  = 50;

var TM_STATE_NON      = 0;
var TM_STATE_START    = 1;
var TM_STATE_RUN      = 2;
var TM_STATE_STOP     = 3;

var TIMER_STACK       = new Array( );

function tmProperties( id, callback  )
{   this.id       = id;
    this.tmid     = 0;
	this.callback = callback;
	this.state    = TM_STATE_NON;
}
function tmFinById( id )
{   for ( var i = 0; i < TIMER_STACK.length; i++ )
	      if ( TIMER_STACK[i].id == id ) return i;
	return -1;
}
function tmFinByClbk( fnCallback )
{   for ( var i = 0; i < TIMER_STACK.length; i++ )
	      if ( TIMER_STACK[i].callback == fnCallback ) return i;
	return -1;
}
function isTimer( id )
{   var i = tmFinById( id );
    if ( i == -1 ) return false;
	return ( TIMER_STACK[i].state == TM_STATE_NON )?false:true;
}
function setTimerCallback( fnTimerCallback )
{   var id = 1;
    for ( var i = 0; i < TIMER_STACK.length; i++ )
	{     if ( TIMER_STACK[i].id >= id ) id = TIMER_STACK[i].id+1;
		  if ( TIMER_STACK[i].callback == fnTimerCallback )
		       return TIMER_STACK[i].id;
	}
	var tm = new tmProperties( id, fnTimerCallback);
	TIMER_STACK.push( tm );	
	return id;
}
function removeTimerCallback( fnTimerCallback )
{   var i = tmFinByClbk( fnTimerCallback );
	if ( i != -1 ) TIMER_STACK.splice( i,1);
}
function killTimer( id )
{   var i = tmFinById( id );
	if ( i == -1 ||  !isTimer(id)) return;
	TIMER_STACK[i].state = TM_STATE_NON;
	self.clearTimeout ( TIMER_STACK[i].tmid );
}
function stopTimer( id )
{   if ( id != undefined )
	{   var i = tmFinById( id );
	    if ( i == -1 ||  !isTimer(id)) return;
		TIMER_STACK[i].state = TM_STATE_STOP;
	}
	else
	{   for ( var i = 0; i < TIMER_STACK.length; i++ )
		{   TIMER_STACK[i].state = TM_STATE_NON;
			self.clearTimeout ( TIMER_STACK[i].tmid );
		}
	}
}
function setTimer( id )
{   var i = tmFinById( id );
	if ( i == -1 || isTimer(id)) 
	{   alert('setTimer: already run'); 
	    return; 
	}//already run
    TIMER_STACK[i].state = TM_STATE_START;
	timerRunner( id );
}

function timerRunner( id )
{   
	if ( !isTimer( id ))
    {   alert( "timerRunner: not started");
	    return;//!!!
    }
	var i = tmFinById( id );
	if ( i == -1 )
	{   alert( "timerRunner: id="+i+" not found");
		return;
	}
	switch( TIMER_STACK[i].state )
	{   case TM_STATE_START:
	         TIMER_STACK[i].callback( TM_STATE_START ); 
	         TIMER_STACK[i].state = TM_STATE_RUN; 
			 break;
		case TM_STATE_RUN:   TIMER_STACK[i].callback( TM_STATE_RUN );   break;
		case TM_STATE_STOP:
		    TIMER_STACK[i].callback( TM_STATE_STOP ); 
			TIMER_STACK[i].state = TM_STATE_NON;
		    break;
		default: return;
	}
	if ( TIMER_STACK[i].state != TM_STATE_NON )
		 TIMER_STACK[i].tmid = self.setTimeout('timerRunner('+id+')', TIMER_DELAY);
}
function timerAction( callbackStart, callbackRun, callbackStop )
{
	var m_fnStart  = (callbackStart == undefined )?null:callbackStart;
	var m_fnExec   = (callbackRun   == undefined )?null:callbackRun;
	var m_fnStop   = (callbackStop  == undefined )?null:callbackStop;
	var m_timer    = null;
	var m_elapsed  = 0;
	var m_timeout  = 0;
	var m_param    = null;
	var m_bCallStopOnKill = false;
	
	this.callstoponkill = function( enable ) { m_bCallStopOnKill = enable; }

	this.starttm   = starttm;
	this.stoptm    = stoptm;
	this.killtm    = killtm;
	this.cleartm   = function( ) { m_elapsed = 0; }
	this.gettm     = function( ) { return m_elapsed; }
	
	
	function starttm( param )
	{   m_param = ( param == undefined )?null:param;
	    if ( !m_timer ) m_timer = setTimerCallback( timerCallback );
	    setTimer( m_timer );
	}
	function stoptm ( ) {  stopTimer( m_timer ); }
	function killtm ( ) 
	{   killTimer( m_timer ); 
	    m_elapsed = 0;
		if ( m_bCallStopOnKill )
		{  if ( m_fnStop  ) m_fnStop ( TM_STATE_STOP,  m_param );
		}
	}
	
	this.setBreakTime = function ( value ) { m_timeout = value; }

	function timerCallback( state )
	{   switch( state )
		{   case TM_STATE_START: m_elapsed = 0; 
		        if ( m_fnStart ) m_fnStart( TM_STATE_START, m_param );
                break;
			case TM_STATE_RUN:
			    if ( m_fnExec  ) m_fnExec ( TM_STATE_RUN,   m_param );	
				if ( m_timeout )
				{   m_elapsed += TIMER_DELAY;
				    if ( m_elapsed > m_timeout )
				         stoptm( m_timer );
				}
			    break;
			case TM_STATE_STOP: 
				if ( m_fnStop  ) m_fnStop ( TM_STATE_STOP,  m_param );	
			    m_elapsed = 0;
			    break;
		}
	}
};

