//CONSTRUCTOR
//   [obj] := an optional object reference who's event's will be listened to.  Default = window
EventBroadcaster = function(obj) {
	this._obj = (obj)? obj : window;
	
	//if this._obj already has an EventBroadcaster object, then return
	if(this._obj.eventBroadcaster) return;

	//setup a reference from the object to this listener
	this._obj.eventBroadcaster = this;

	//create a new listener store
	this._listeners = new Object();
}

//add a listener
//  evt := the event to listen to (ie. "onload")
//  id  := a unique event listener id (per event)...this will enable remove the listener later
//  meth:= the callback method - can be a string or function
// [obj]:= an optional object
EventBroadcaster.prototype.addListener = function(evt,id,meth,obj) {
	//create the event contianer if it doesn't exist
	if(!this._listeners[evt]) this._listeners[evt] = new Object();
	//if meth is a string and no object was passed in, then we'll assume it's on the window object
	if(typeof meth == 'string' && !obj) obj = window;
	
	//if meth is not a string and an object was passed, null out the object
	if(typeof meth != 'string' && obj) obj = null;

	//attach this's broadcast method to this._obj's "evt" (event)
	var call_broadcast = "this.eventBroadcaster.broadcast('"+evt+"',arguments)";
	var addFoundEvent = false;
	
	//if an event handler for this object/event is already defined, we'll need to push it onto the listener stack
	if(this._obj[evt] && String(this._obj[evt]).indexOf(call_broadcast) == -1) {
		 this._obj['_predefined_'+evt] = this._obj[evt];
		 addFoundEvent = true;
	}

	//set this._obj's event handler to this' broadcast method
	this._obj[evt] = new Function(call_broadcast);

	//if we found an event, add it to the stack now
	// changed by cz: this was causing infinite loop, i added the null check but
	// this block is probably not doing what's intended originally.  temp fix.
	if(addFoundEvent && this._obj['_predefined_'+evt]==null) {
		this.addListener(evt,'_listener_found_event','_predefined_'+evt,this._obj);
	}

	//add this new listener
	this._listeners[evt][id] = {
		meth : meth,
		obj  : obj	
	}

}

//remove a listener
EventBroadcaster.prototype.removeListener = function(evt,id) {
	if(this._listeners[evt] && this._listeners[evt][id]) delete this._listeners[evt][id];
}

//get all listeners for requested event
EventBroadcaster.prototype.getEvent = function(evt) {
	return this._listeners[evt];
}

//broadcast an event to all of the event's listeners
EventBroadcaster.prototype.broadcast = function(evt,args) {
	var listeners = this.getEvent(evt);
	//usually, args only contains the event object, so reference it directly instead of embedding it in the args array
	if(args) args = (args.length > 1)? args : args[0];
	//broadcast
	for(var i in listeners) {
		var listener = listeners[i];
		//if we stored an object for this listener, call the stored method (string) on this object
		if(listener.obj) {
			listener.obj[listener.meth](args);
		//otherwise the meth should be a function reference, so call it
		} else {
			listener.meth(args);
		}
	}
}

//create the window event listener by default
// it won't listen to events or override any event handlers until a listener is added
new EventBroadcaster();
