/**
 * @required: Schematic
 * @required: Schematic.Flag
**/

Schematic.Event = function() {

	if (!(Schematic.Flag.W3)) {
		return;
	}

	return {
		
		stack : [],
		
		/**
		 * Original version written by Dean Edwards: http://dean.edwards.name/weblog/2005/10/add-event/
		 * With input from Tino Zijdel - crisp@xs4all.nl
		 * Branching version 2007-04-27 by Tino Zijdel
		**/
		add : function() {
			if (document.addEventListener) {
				return function(element, type, handler) {
					
					if (typeof handler !== "object") {
						handler = [handler];
					}
					for (var i = 0, j = handler.length; i < j; i++) {
						Schematic.Event.cache.add(element, type, handler[i]);
						if (type === "DOMContentLoaded") {
							Schematic.Event.domLoad(handler[i]);
						} else {
							element.addEventListener(type, handler[i], false);
						}
					}
					
				};
			} else {
				var guid = 1;
				return function(element, type, handler) {
					
					if (typeof handler !== "object") {
						handler = [handler];
					}
					for (var i = 0, j = handler.length; i < j; i++) {
					    Schematic.Event.cache.add(element, type, handler[i]);
						if (type === "DOMContentLoaded") {
							Schematic.Event.domLoad(handler[i]);
						} else {
							if (!handler[i].$$guid) {
								handler[i].$$guid = guid++;
							}
							if (!element.events) {
								element.events = {};
							}
							if (!element.events[type]) {
								element.events[type] = {};
								if (element["on" + type]) {
									element.events[type][0] = element["on" + type];
								}
								element["on" + type] = Schematic.Event.handle;
							}
							element.events[type][handler[i].$$guid] = handler[i];
						}
					}
					
				};
			}
		}(),
		
		handle : function(e) {
			e = e || Schematic.Event.fix(window.event);
			var handlers = this.events[e.type], returnValue;
			for (var i in handlers) {
				if (handlers.hasOwnProperty(i) && handlers[i].call(this, e) === false) {
					handlers[i].call(this, e);
				}
			}
			return returnValue;
		},
		
		fix : function(e) {
			e.stopPropagation = Schematic.Event.stopPropagation(e);
			return e;
		},
		
		preventDefault : function(e) {
			e.preventDefault ? e.preventDefault() : e.returnValue = false;
		},
		
		stopPropagation : function(e) {
			e.stopPropagation ? e.stopPropagation() : e.cancelBubble = true;
		},
		
		target : function(e) {
			return e.target || e.srcElement;
		},
		
		remove : function() {
			if (document.removeEventListener) {
				return function(element, type, handler) {
					if (typeof handler !== "object") {
						handler = [handler];
					}
					for (var i in handler) {
						element.removeEventListener(type, handler[i], false);
					}
				};
			} else {
				return function(element, type, handler) {
					if (typeof handler !== "object") {
						handler = [handler];
					}
					for (var i in handler) {
						if (element.events && element.events[type] && handler[i].$$guid) {
							delete element.events[type][handler[i].$$guid];
						}
					}
				};
			}
		}(),
	
		/**
		 * EventCache Version 1.0
		 * Copyright 2005 Mark Wubben
 		 * 
		 * Provides a way for automagically removing events from nodes and thus preventing memory leakage.
		 * See <http://novemberborn.net/javascript/event-cache> for more information.
		 * 
		 * This software is licensed under the CC-GNU LGPL <http://creativecommons.org/licenses/LGPL/2.1/>
		**/
		
		/**
		 * Event Cache uses an anonymous function to create a hidden scope chain.
		 * This is to prevent scoping issues.
		**/
		cache : function() {
			var listEvents = [];
			return {
				listEvents : listEvents,
				add : function(obj, type, fn) {
					listEvents.push(arguments);
				},
				flush : function() {
					var i,
					    item;
					for (i = listEvents.length - 1; i >= 0; i = i - 1) {
						item = listEvents[i];
						if (item[0].removeEventListener) {
							item[0].removeEventListener(item[1], item[2], item[3]);
						}
						/* From this point on we need the event names to be prefixed with "on" */
						if (item[1].substring(0, 2) != "on") {
							item[1] = "on" + item[1];
						}
						if (item[0].detachEvent) {
							item[0].detachEvent(item[1], item[2]);
						}
						item[0][item[1]] = null;
					}
				}
			};
		}(),
		
		/**
		 * Load objects when the DOM loads
		 * @author Dean Edwards / Matthias Miller / John Resig / Mark Wubben / Paul Sowden
		**/
		compile : function() {
			if (arguments.callee.done) {
				return;
			}
			arguments.callee.done = true;
			for (var i = 0; Schematic.Event.stack[i] !== undefined; i++) {
			  Schematic.Event.stack[i]();
			}
		},
		
		domLoad : function(e) {
			this.stack.push(e);
			if (document.addEventListener) {
				document.addEventListener("DOMContentLoaded", Schematic.Event.compile, null);
			}
			/*@cc_on document.write("<script id=__ready defer src=//:><\/script>");
			document.all.__ready.onreadystatechange = function() {
				if (this.readyState == "complete") {
					this.removeNode();
					Schematic.Event.compile();
				}
			};@*/
			if (/KHTML|WebKit/i.test(navigator.userAgent)) { 
				var timer = setInterval(function() {
					if (/loaded|complete/.test(document.readyState)) {
						clearInterval(timer);
						Schematic.Event.compile();
					}
				}, 10);
			}
			window.onload = Schematic.Event.compile;
		}
		
	};
	
}();

/**
 * Flush the cache onunload
**/
Schematic.Event.add(window, "unload", Schematic.Event.cache.flush);