var Cathmhaol = window.Cathmhaol || {};

/**
* Creates a user-defined event with a handler mechanism
*
* @author	Robert King (hrobertking@cathmhaol.com)
*/
Cathmhaol.Event = function() {
	/**
	* @method	Listens for a specific event on an object. When the event occurs, the function (fn) is executed
	* @returns	{void}
	* @argument	{string|node} o
	* @argument	{string} evt
	* @argument	{function} fn
	* @argument	{object} obj
	*/
	this.listen = function (o, evt, fn, obj) {
		var n = (typeof(o) == "string") ? document.getElementById(o) : o;
		if (!n || !n.nodeName) { return; }
		if (!fn || !fn.call) { return; }

		fn = function(e) { return fn.call((obj || n), me.triggered(e, n), obj); };

		if (window.addEventListener) {
			n.addEventListener(evt, fn, false);
		} else if (window.attachEvent) {
			n.attachEvent("on" + evt, fn);
		}
	},

	/**
	* @method	Subcribes a function to an event
	* @returns	{void}
	* @argument	{function} fn
	* @argument	{object} scope
	*/
	this.subscribe = function(fn, scope) {
		if (typeof(fn) == "function") {
			_l.push({fn: fn, scope: (scope) ? scope: null});
		}
	},

	/**
	* @method	Triggers the event
	* @returns	{void}
	*/
	this.trigger = function() {
		if (_l.length) {
			var args = [].slice.call(arguments, 0), i, ret = true, handler, handlers = _l.slice();
			for (i = 0; i < _l.length; ++i) {
				handler = handlers[i];
				if (handler) {
					try {
						ret = handler.fn.call(handler.scope || window, args);
					} catch(ex) {
					}
					if (false === ret) {
						break;
					}
				}
			}
			me.unsubscribe();
		}
		return;
	}

	/**
	* @method	Returns the event that occurred.
	* @returns	{object}
	*/
	this.triggered = function(e) {
		var evt = e || window.event;
		if (!evt) {
			var c = me.get.caller;
			while (c) {
				evt = c.arguments[0];
				if (evt && Event == ev.constructor) {
					break;
				}
				c = c.caller;
			}
		}
		return evt;
	},

	/**
	* @method	Unsubcribes a function from an event
	* @returns	{void}
	*/
	this.unsubscribe = function() {
		var l = _l.length, index;
		for (index = l - 1; index > -1; index--) {
			var s = _l[index];
			if (s) {
				delete s.fn;
				delete s.scope;
			}
			_l.splice(index, 1);
		}
		_l = [];
	},

	/**
	* @private
	* @property	The list of subsribers (consumers) to the event.
	* @type	{object[]}
	*/
	var _l = new Array();

	var me = this;
};

