var Cathmhaol = window.Cathmhaol || {};

/**
* @library     Cathmhaol.EventHandler
* @description Creates an event handler mechanism
* @author      Robert King
*
* @example     var oBehaviorHandler = new Cathmhaol.EventHandler(); oBehaviorHandler.add(document.getElementById("clicker"), "click", clicker_onClick);
*/
Cathmhaol.EventHandler = function() {
};

Cathmhaol.EventHandler.prototype = {
	/**
	* @method      add
	* @description Adds an event handler to an object
	* @returns {void}
	* @param {node} obj                      The object to which the event handler should be added
	* @param {string} eventType              The event to be handled. Must be one of click, doubleclick
	* @param {string|function} eventHandler  The function to be executed when the event fires
	*/
	add: function(obj, eventType, eventHandler) {
		this.handler = eventHandler;
		var objCurrentHandler = eval("obj.on"+eventType.toLowerCase());
		if (objCurrentHandler) {
			this._concat(objCurrentHandler, eventHandler);
		}
		if (typeof this.handler == "string") { this.handler = new Function(this.handler); }
		if (obj.addEventListener) {
			obj.addEventListener(eventType.toLowerCase(), this.handler, false);
		} else if (obj.attachEvent) {
			eval("obj.on"+eventType.toLowerCase()+"="+this.handler);
		}
	},

	/**
	* @private
	* @method      _concat
	* @description Adds the new event handler to existing handlers
	* @returns {void}
	* @param {function} existingFunction  Handlers currently attached
	* @param {function} newFunction       Handler to be added
	*/
	_concat: function(existingFunction, newFunction) {
		var objNewFunction;
		switch(typeof existingFunction) {
			case "string":
				switch (typeof newFunction) {
					case "string":
						this.handler = new Function(existingFunction+"; "+newFunction);
						break;
					case "function":
						this.handler = new Function(existingFunction+"; "+this._strippedNamedFunction(newFunction.toString())+"();");
						break;
				}
				break;
			case "function":
				switch (typeof newFunction) {
					case "string":
						this.handler = new Function(this._strippedAnonymousFunction(existingFunction.toString())+newFunction);
						break;
					case "function":
						this.handler = new Function(this._strippedAnonymousFunction(existingFunction.toString())+this._strippedNamedFunction(newFunction.toString())+"();");
						break;
				}
				break;
			default:
				switch (typeof newFunction) {
					case "string":
						this.handler = new Function(newFunction);
						break;
					case "function":
						this.handler = newFunction;
						break;
				}
				break;
		}
	},

	/**
	* @private
	* @method      _strippedAnonymousFunction
	* @description This translates the anonymous function declared by a string back to a string
	* @returns {string}
	* @param {string} functionSource  The JavaScript source for the function
	*/
	_strippedAnonymousFunction: function(functionSource) {
		returnSource = functionSource.replace(/function\sanonymous\(\)\s\{\n?/, "");
		returnSource = returnSource.substr(0, returnSource.length);
		return returnSource;
	},

	/**
	* @private
	* @method      _strippedNamedFunction
	* @description This translates the named function into a string
	* @returns {string}
	* @param {string} functionSource  The JavaScript source for the function
	*/
	_strippedNamedFunction: function(functionSource) {
		returnSource = functionSource.replace(/function\s/, "");
		returnSource = returnSource.substring(0, returnSource.indexOf("("));
		return returnSource;
	}
};
