//_______________________________________________________________________
function Broadcaster(listenerDock_obj){
// Allows arbitrary events to be defined, triggered and handled

	var self					= this;
	var events_arr				= new Array();
	var eventBuffers_arr		= new Array();
	
	listenerDock_obj.addEventListener = addEventListener;
	listenerDock_obj.removeEventListener = removeEventListener;
	
	//-------------------------------------------------------------------
	function checkEventValidity(eventType_str){
		
		if(events_arr.hasOwnProperty(eventType_str)){
			var valid_bool	= true;
		}else{
			valid_bool		= false;
			throw new Error('The event "'+eventType_str+'" has not been defined on this object');
		}
		return valid_bool;
	};
	//-------------------------------------------------------------------
	function removeEventListener(eventType_str,listener_func,ignoreNonExistence_bool){

		var removed_bool			= false;
		if(checkEventValidity(eventType_str)){
			var handlers_arr		= events_arr[eventType_str];
			for(var index=0; index<handlers_arr.length; index++){
				if(handlers_arr[index] === listener_func){
					handlers_arr.splice(index,1);
					removed_bool	= true;
					break;
				}
			}
		}
		if(!removed_bool && !ignoreNonExistence_bool){
			throw new Error('The supplied function is not a registered listener for "'+eventType_str+'" events');
		}
		return removed_bool;
	};
	//-------------------------------------------------------------------
	function addEventListener(eventType_str,listener_func){
		
		var eventId_str				= false;
		if(checkEventValidity(eventType_str)){
			var eventType_arr		= events_arr[eventType_str];
			eventType_arr.push(listener_func);
			eventType_arr			= Array.unique(eventType_arr);
			eventId_str				= eventType_str+'_'+eventType_arr.length;
		}
		return eventId_str;
	};
	//___________________________________________________________________
	this.createEventType = function(eventType_str){
	// defines a valid event type
	
		if(events_arr.hasOwnProperty(eventType_str)){
			throw new Error('Event already defined');
		}else{
			events_arr[eventType_str]	= new Array();
			eventBuffers_arr[eventType_str] = new Broadcaster.EventBuffer(eventType_str,this);
		}
	};
	//___________________________________________________________________
	this.bufferEvent = function(evtType_str,evtParameters){
	// Triggers the event only after a slight delay. If the event is 
	// requested again during the delay, the delay is reset and the orignal
	// call is cancelled. Prevents multiple event firings for near simultaneous
	// triggers
	
		eventBuffers_arr[evtType_str].triggerEvent(evtParameters);
	};
	//___________________________________________________________________
	this.triggerEvent = function(eventType_str,eventParameters){
		
		var returnVal				= true;
		
		if(checkEventValidity(eventType_str)){
			// make a copy of required handlers in case handlers
			// remove themselves during execution
			var handlersCopy_arr		= new Array();
			var liveHandlers_arr		= events_arr[eventType_str];
			for (var index=0; index<liveHandlers_arr.length; index++){
				handlersCopy_arr.push(liveHandlers_arr[index]);
			}
					
			// execute handlers
			for(index=0; index<handlersCopy_arr.length; index++){
				handlersCopy_arr[index](eventParameters);
			}
			returnVal				= false;
		}	
		return returnVal;
	};
	//___________________________________________________________________
};
//_______________________________________________________________________
Broadcaster.EventBuffer = function(eventType_str,broadcaster){
	
	var parameters;
	var bufferId_int;
	var buffer_ms		= 30;
	
	//-------------------------------------------------------------------
	function fireEvent(){
		
		broadcaster.triggerEvent(eventType_str,parameters);
	};
	//___________________________________________________________________
	this.triggerEvent = function(parameters_arg){
		
		parameters		= parameters_arg;
		bufferId_int	= window.superceedCall(fireEvent,buffer_ms,bufferId_int);
	}
};	//___________________________________________________________________
//_______________________________________________________________________
