/**
 * RoadBook Object, allow management of roadbook planning element
 * Developed for Mootools v1.2.4
 *
 * @class EventsManager
 * @author Nicolas Grandgirard <ngrandgirard@agenceinteractive.com>
 * @classDescription Event manager which launch severals function step by step
 * @copy Agence Ineractive
 */
var EventsManager = new Class({ 
	
	Implements: [Events, Options],
	
	//Options of EventsManager Object
	options:
	{
		/**
		 * @param oEvents -> new Hash({ (string)nameEvent: (function)function });
		 * with function type of:
		 
		 	- necessary to end with fireEvent('nextStep');
		 	- necessary to use param which is oEventsManager event is not define;
		 	
			var fShowHideNewsletter = function( oEventsManager )
			{
				<!-- script -->
				
				oEventsManager.fireEvent('nextStep');
			};
		 
		 * @param iDelayTimeOut -> int which is value of outTimer
		 *
		 * @return void
		 */
		oEvents: new Hash(),
		iDelayTimeOut: 10000
    },

    /**
	 * Init EventsManager object
	 * @return void
	 */
	initialize: function( options ){
    	
		this.setOptions( options );
		
		// init properties from options
		this.iDelayTimeOut = this.options.iDelayTimeOut;
		
		// init properties
		this.iCurrentEvent 		= null;
		this.aKeysObjectEvents 	= null;
		this.oTimer 			= null;
		this.isLaunched 		= false;
		this.oEvents 			= new Hash();
		
		// register events from oEvents option
		if( this.options.oEvents != null )
		{
			this.options.oEvents.each( function( elem, index ){
				this.registerEvent( index, elem );
			}.bind(this) );
		}
		
		// add first event nextStep
		this.addEvent('nextStep', this.nextStep);
	},
	
	/**
	 * register name|value of event|functions in object hash
	 *
	 * @param sName -> string which is name of event
	 * @param fFunction -> function which will be called
	 *
	 * @return void
	 */
	registerEvent: function( sName, fFunction )
	{
		// register event if not exist
		if( !this.oEvents.has( sName ) )
			this.oEvents.set( sName, fFunction );
	},
	
	/**
	 * addEvents registered on this object
	 *
	 * @return void
	 */
	addEvents: function()
	{
		// add events registered on this
		this.oEvents.each( function( elem, index ){
			this.addEvent( index, elem.pass(this) );
		}.bind(this) );
	},
	
	/**
	 * launch first function which is registered in object
	 * 
	 * @return void
	 */
	launch: function(){

		// launch first step if not already launch
		if( this.isLaunched == false )
		{
			this.isLaunched = true;
			
			// get keys of object
			if( this.aKeysObjectEvents == null )
				this.aKeysObjectEvents = this.oEvents.getKeys();
			
			// launch first step
			if( this.iCurrentEvent == null && this.aKeysObjectEvents.length > 0 )
			{
				this.iCurrentEvent = 0;
				this.fireEvent( this.aKeysObjectEvents[this.iCurrentEvent] );
			}
		}
	},
	
	/**
	 * launch next function registered when fireevent('nextstep') by previous function finished
	 *
	 * @return void
	 */
	nextStep: function(){
		
		this.iCurrentEvent++;
		if( this.aKeysObjectEvents[this.iCurrentEvent] )
		{
			// start timer if not started
			this.startTimer();
		
			if( this.iCurrentEvent == (this.aKeysObjectEvents.length - 1) )
				this.stopTimer();
			
			var sEvent = this.aKeysObjectEvents[this.iCurrentEvent];
			this.fireEvent( sEvent );
		}
	},
	
	/**
	 * @return throw error if a function is timeout
	 */
	isTimeOut: function()
	{
		throw ( 'Time Out for event ' + this.aKeysObjectEvents[this.iCurrentEvent] );
	},
	
	/**
	 * stop out timer
	 *
	 * @return void
	 */
	stopTimer: function(){
		if( this.oTimer != null )
			this.oTimer = $clear(this.oTimer);
	},
	
	/**
	 * start out timer
	 *
	 * @return void
	 */
	startTimer: function(){
		if( this.oTimer == null )
			this.oTimer = this.isTimeOut.delay( this.iDelayTimeOut, this );
		else
		{
			$clear( this.oTimer);
			this.oTimer = this.isTimeOut.delay( this.iDelayTimeOut, this );
		}
	}
});

EventsManager.getInstance = function getInstance()
{
	if (oInstance instanceof 'undefined')
	{
		var oInstance = new this();
	}
	
	return oInstance;
}

