/*************************
EventsManager
	1. I want to use it for DOM Events. 
		- MTVM.EventsManager is acting more like a wrapper around jQuery/PrototypeJS event binding in this mode.
		- IMPORTANT: DOM listeners are dispatched out to listen right before open BODY tag.
		
		[SAMPLE CODE]
		
			>>>>>>>>>>> Create Your DOM Event <<<<<<<<<<<<
			MTVM.EventsManager.events.onSearchBoxClick = new MTVM.EventsManager.events.BaseEvent()	
			MTVM.EventsManager.events.onSearchBoxClick.invoke = function() //invoke function is required for DOM event
			{
				if(typeof jQuery != "undefined")
				{						
					$J(window).load(	//REQUIRED
						function()
						{
							//YOUR CUSTOM STUFF GOES HERE:
							$J('#searchInputBox').click(function(){
								MTVM.EventsManager.events.onSearchBoxClick.__dispatchAllCallbacks();
							})
						}
					)
				}
			}
			//SOME EXPLANATION:
			//$J(window).load() is required to wrap around all non-domready/window loaded events, ie, click events, mouse events, etc. etc. 
			//This is because DOM listeners are dispatched out to listen before body tag and the rest of the dom are loaded.

			//MORE RAMBLING: 
			//You can add your DOM Event's invoke function as a listener of MTVM.eventsManager.events.onWindowLoaded 
			//or MTVM.eventsManager.events.onDomLoaded. By doing so, you wouldnt need to use $J(window).load to wrap your DOM event.
			
			>>>>>>>>>>> Add Event Listeners <<<<<<<<<<<<
			MTVM.EventsManager.addListener("onSearchBoxClick", myFunctionhere, myFunctionContext);
			OR
			MTVM.EventsManager.events.onSearchBoxClick.addListener(myFunctionhere, myFunctionContext);			
			//myFunctionContext is not a required value. It's only necessary if you want to fire the callback within the scope you want to specify.
			
		[/END SAMPLE CODE]
	
	2. I want to use it for Non-DOM Events
		- Any custom event you want to broadcast/listen on.
		
		[SAMPLE CODE]		
			>>>>>>>>>>> Create Custom Event <<<<<<<<<<<<
			MTVM.EventsManager.events.onSomethingIsReady = new MTVM.EventsManager.events.BaseEvent('NOT_DOM_EVENT'); 
			//"NOT_DOM_EVENT" can be any value except null. If null, EventsManager will treat it as a DOM event by default.

			
			>>>>>>>>>>> Add Event Listeners <<<<<<<<<<<<
			MTVM.EventsManager.addListener("onSomethingIsReady", myFunctionhere, myFunctionContext);
			OR
			MTVM.EventsManager.events.onSomethingIsReady.addListener(myFunctionhere, myFunctionContext);			
			//myFunctionContext is not a required value. It's only necessary if you want to fire the callback within the scope you want to specify.
			
			
			>>>>>>>>>>>Broadcast the EVENT <<<<<<<<<<<<
			Broadcast the event and let loose all your callbacks
			
			MTVM.EventsManager.broadcast("onSomethingIsReady");
			
		[/END SAMPLE CODE]
		
		
		
		
TODO: A new listerner mode for NON-DOM listeners to be persistent. Ie, the listener is not popped out after the event is broadcasted.
*************************/




MTVM.EventsManager = {
	events: {},
	dispatchDOMListeners:	function() //this is a special dispatch function for DOM event listeners. Must be fired before BODY tag
	{
		MTVM.logger.log("MTVM.EventsManager.dispatchDOMListeners ", 1);	
		for(var event in this.events)
		{		
			if(typeof this.events[event].invoke == "function" && this.events[event].eventType == 'DOM')
			{
				this.events[event].invoke();
			}
		}
	},

	addListener: function(myEvent, callbackFunc, callbackContext) //shortcut function for MTVM.EventsManager.events.onMYEVENT.addListener()					
	{
		try{
			MTVM.logger.log("MTVM.EventsManager.addListener " + myEvent, 1);	
			MTVM.EventsManager.events[myEvent].addListener(callbackFunc, callbackContext);
		}
		catch(e)
		{
			MTVM.logger.log("MTVM.EventsManager.addListener "+e, 2);
		}
	},

	broadcast: function(myEvent)
	{
		try{
			MTVM.logger.log("MTVM.EventsManager.broadcast " + myEvent, 1);
			MTVM.EventsManager.events[myEvent].__dispatchAllCallbacks();
		}catch(e)
		{
			MTVM.logger.log("MTVM.EventsManager.broadcast: "+myEvent+": "+e, 2);
		}
	},
	
	removeAllListeners: function(myEvent) //remove all listeners for an event
	{
		try{
			MTVM.logger.log("MTVM.EventsManager.removeAllListeners " + myEvent, 1);
			if(MTVM.EventsManager.events[myEvent]){
				MTVM.EventsManager.events[myEvent].__removeAllCallbacks();
			}
		}catch(e)
		{
			MTVM.logger.log("MTVM.EventsManager.removeAllListeners: "+myEvent+": "+e, 2);
		}		
	}
}


MTVM.EventsManager.events.BaseEvent = function(eventType)
{		
	this.eventType = eventType?eventType:"DOM";	//eventType indicates whether it's a DOM event or a regular event. DOM event listeners will be activated/dispatched before BODY tag comes up.
	this.callbacks = new Array();	//each element of the array contains a hash with two values: callbackFunction and callbackContext
}

MTVM.EventsManager.events.BaseEvent.prototype.addListener = function(callbackFunc, callbackContext) //you can add the context which the callback function is scoped in.
{
	MTVM.logger.log("MTVM.EventsManager.events.BaseEvent adding listener " + callbackFunc +" <br/> eventType ="+this.eventType, 1);
	
	this.callbacks.push({});
	this.callbacks[this.callbacks.length-1]['callbackFunction'] = callbackFunc;
	this.callbacks[this.callbacks.length-1]['callbackContext'] = callbackContext;	
}

MTVM.EventsManager.events.BaseEvent.prototype.__getAndRemoveLastCallback = function() //not in use
{
	var callbackObj = this.callbacks[this.callbacks.length-1];	
	this.callbacks.pop();
	MTVM.logger.log("MTVM.EventsManager.events.BaseEvent __getAndRemoveLastCallback " + callbackObj, 1);

	return callbackObj;	
}


MTVM.EventsManager.events.BaseEvent.prototype.__getAndRemoveFirstCallback = function()
{
	var callbackObj = this.callbacks[0];	
	this.callbacks.shift();
	MTVM.logger.log("MTVM.EventsManager.events.BaseEvent __getAndRemoveFirstCallback " + callbackObj, 1);
	
	return callbackObj;	
}


MTVM.EventsManager.events.BaseEvent.prototype.__removeAllCallbacks = function()
{
	var emptyArray = new Array();
	this.callbacks = emptyArray;
	MTVM.logger.log("MTVM.EventsManager.events.BaseEvent __removeAllCallbacks ", 1);
}

MTVM.EventsManager.events.BaseEvent.prototype.__dispatchAllCallbacks = function()
{
	var currCallback = null;
	var arrayLength = this.callbacks.length
	MTVM.logger.log("MTVM.EventsManager.events.BaseEvent __dispatchAllCallbacks ", 1);
	for(var i=0; i<arrayLength; i++)
	{
		currCallbackObj = this.__getAndRemoveFirstCallback();	
		if(typeof currCallbackObj.callbackFunction == "function")
		{			
			if(currCallbackObj.callbackContext != null)
			{
				currCallbackObj.callbackFunction.apply(currCallbackObj.callbackContext);
			}else
			{
				currCallbackObj.callbackFunction();
			}
		}
	}	
}


/******************** CUSTOM CREATED EVENTS ****************************/


MTVM.EventsManager.events.onDomLoaded = new MTVM.EventsManager.events.BaseEvent()	
MTVM.EventsManager.events.onDomLoaded.invoke = function() //invoke function is required for DOM event
{
	if(typeof jQuery != "undefined")
	{	
		$J(document).ready(function(){
			MTVM.EventsManager.events.onDomLoaded.__dispatchAllCallbacks();
		})
	}
}


MTVM.EventsManager.events.onWindowLoaded = new MTVM.EventsManager.events.BaseEvent()
MTVM.EventsManager.events.onWindowLoaded.invoke = function() //invoke function is required for DOM event
{
	window.onload = function(){
		MTVM.EventsManager.events.onWindowLoaded.__dispatchAllCallbacks();
	}
}

MTVM.EventsManager.events.onPlaylistBreadcrumbReady = new MTVM.EventsManager.events.BaseEvent('NOT_DOM_EVENT');
MTVM.EventsManager.events.onDnDPopUpReady 			= new MTVM.EventsManager.events.BaseEvent('NOT_DOM_EVENT');
MTVM.EventsManager.events.onDnDSongTitleReady 		= new MTVM.EventsManager.events.BaseEvent('NOT_DOM_EVENT');

MTVM.EventsManager.events.onVideoDetailsReloaderDataSerivceReady	= new MTVM.EventsManager.events.BaseEvent('NOT_DOM_EVENT');
MTVM.EventsManager.events.onFluxComments3Ready 						= new MTVM.EventsManager.events.BaseEvent('NOT_DOM_EVENT');
MTVM.EventsManager.events.onFluxContentAction2Ready 				= new MTVM.EventsManager.events.BaseEvent('NOT_DOM_EVENT');
MTVM.EventsManager.events.onFluxUsageReady 							= new MTVM.EventsManager.events.BaseEvent('NOT_DOM_EVENT');

MTVM.EventsManager.events.onShortUrlReady							= new MTVM.EventsManager.events.BaseEvent('NOT_DOM_EVENT');

