/* 

	OK. Everyone else has done one, but I'm just picky enough to need to roll my own, I guess.
	So here's my custom javascript event listener / broadcaster class or what have you. I'm
	just going to call it ES (short for event switch). My analog for this is a physical network
	switch: it sits there in the middle of everything, and passes messages where they need to
	go. Obviously, this is a little more specific, but the concept is the same.
	
	Credit to Josh Davis for his implementation using arrays, which I think is really elegant
	overall.
	
	Also thanks to Justin @ GeekDaily and Seth Dillingham's for other implementations of this -
	which were great, but a little too much for me.	
	
	Prototype required for class instantiation, but you could do without it.
	
*/

/* create class using Prototype's class.create */
var ES = Class.create();

/* assign everything else to our object prototype */
ES.prototype = {

	/* initialize hook also provided by prototype - so 
		this will execute when 'new ES()' is called from anywhere */
	initialize: function() {
		/* just setting up an empty object to hold all of our event subscribers */
		this.subscribers = {};
		/* and a counter which will serve as a unique id number for subscribers */
		this.sub_id = 0;
	},
	
	/* create new object in subscribers, referenced by subscriber id */
	/* increment our subscriber id and return the id number just assigned */
	register: function() {
		this.subscribers[this.sub_id] = {};
		this.sub_id++;
		return this.sub_id-1;
	},
	
	/* subscribe takes the the following:
		id: unique id returned previously by register
		el: the element on which the event being listened for will occur - see note below
		ev: the event which you with to receive notification of - see note above
		callback: reference to the callback function - note this is an reference, not a string
		scope: reference to the object you wish your callback scoped to - probably will be 'this' most of the time
		OPTIONAL: additional arguments beyond -scope- will be sent along to callback
		
		NOTE: el and ev will be ARBITRARY string values. They only need to match the request that you will issue when you fire the corresponding event later. So if you subscribe with EventSwitch.subscribe("mystring",""myevent"), you later will fire that event with EventSwitch.fire("mystring","myevent"). If these don't all match up, you'll get nothin'

	*/
	subscribe: function(id,el,ev,callback,scope) {
		/* if there isn't a subscribers 'el' in our list, we create one as a new object */
		if (this.subscribers[id][el]==undefined) {
			this.subscribers[id][el] = {};
		}
		/* if there isn't an event 'ev' in subsbribers[el], we create one as a new object */
		if (this.subscribers[id][el][ev] == undefined) {
			this.subscribers[id][el][ev] = {};
		}
		/* we assign the supplied callback to subscribers[el][ev]['callback'] -
			note that I'm assuming for now that this would overwrite existing entries */
		this.subscribers[id][el][ev]["callback"] = callback;
		/* ditto for scope */
		this.subscribers[id][el][ev]["scope"] = scope;
		/* any additional arguments are saved to an array 'args' which is assigned to subs[el][ev]['args'] */
		if (arguments.length > 5) {
			this.subscribers[id][el][ev]["args"] = [];
			for (var i=5; i<arguments.length;i++) {
				this.subscribers[id][el][ev]["args"].push(arguments[i]);
			}
		}
	},

	unsubscribe: function(id, el, ev) {
		/* this function essentially reverses the first 6 lines of subscribe, and should destroy or
			free up for garbage collection either objects or specific events that we unsubscribe */
		if (this.subscribers[id][el][ev]) {
			this.subscribers[id][el][ev] = undefined;
		}
		if (this.subscribers[id][el]) {
			this.subscribers[id][el] = undefined;
		}
		if (this.subscribers[id]) {
			this.subscribers[id] = undefined;
		}
	},
	
	fire: function(el,ev) {
		/* handle informal arguments */
		if (arguments.length > 2) {
			var args = [];
			for (var i=2; i<arguments.length;i++) {
				args.push(arguments[i]);
			}
		}

		/* find our event and element if they exist in our subscribers object */
		for (var i in this.subscribers) {
			if (this.subscribers[i][el]) {
				if (this.subscribers[i][el][ev]) {
					/* apply our callback with the corresponding scope and arguments - probably need to clean this up a bit... */
					this.subscribers[i][el][ev]["callback"].apply(this.subscribers[i][el][ev]["scope"],args);
				}
			}
		}
	}

}

/* create EventSwitch on the window object when load is complete */
Event.observe(window,"load",function() {window.EventSwitch = new ES();});