var WindowEventQueue =
{
	load: [],
	unload: [],
	beforeunload: []
}

AttachDOMEvent(window, "load", ProcessWindowLoadEvents);
AttachDOMEvent(window, "unload", ProcessWindowUnloadEvents);
AttachDOMEvent(window, "beforeunload",  ProcessWindowBeforeUnloadEvents);

function ProcessWindowLoadEvents() { ProcessWindowEvents("load"); };
function ProcessWindowUnloadEvents() { ProcessWindowEvents("unload"); };
function ProcessWindowBeforeUnloadEvents() { ProcessWindowEvents("beforeunload"); };

function ProcessWindowEvents(eventName)
{
	var handlers = WindowEventQueue[eventName];
	for(var i=0;i<handlers.length;i++)
	{
		var fn = handlers[i];
		if(typeof(fn) == "function")
		{
			fn();
		}
	}
}

function AttachDOMEvent(element, eventName, fn, capture)
{
	if(element.addEventListener)
	{
		if(capture == null) capture = false;
		element.addEventListener(eventName, fn, capture);
	}
	else if(element.attachEvent)
	{
		element.attachEvent("on"+eventName, fn);
	}
}

function DetachDOMEvent(element, eventName, fn, capture)
{
	if(element.removeEventListener)
	{
		if(capture == null) capture = false;
		element.removeEventListener(eventName, fn, capture);
	}
	else if(element.detachEvent)
	{
		element.detachEvent("on"+eventName, fn);
	}
}

function AddEventManager(jsType)
{
	for(var m in EventManager.prototype)
	{
		jsType.prototype[m] = EventManager.prototype[m];
	}
}

function EventManager()
{
}

EventManager.prototype.addEventListener = 
function(eventName, fn)
{
	if(eventName == "load" || eventName == "unload" || eventName == "beforeunload")
	{
		WindowEventQueue[eventName].push(fn);
	}
	else
	{
		if(!this.events)
			this.events = {};

		if(this.events[eventName] == null)
			this.events[eventName] = [];

		this.events[eventName].push(fn);
	}
}

EventManager.prototype.removeEventListener =
function(eventName, fn)
{
	if(!this.events) return;
	var evts = this.events[eventName];
	if(evts == null) return;

	for(var i in evts)
	{
		if(evts[i] == fn)
		{
			evts.splice(i, 1);
			break;
		}
	}
}

EventManager.prototype.hasListeners =
function(eventName)
{
	return (this.events && (this.events[eventName] != null))
}

EventManager.prototype.dispatchEvent =
function(eventName, evt, args)
{
	if(!this.events) return true;

	var result = true;
	//processes callbacks FIFO
	var evts = this.events[eventName];
	if(evts == null) return true;

	var a = [evt].concat(args);
	var callbackResult;
	for(var i=0; i<evts.length; i++)
	{
		callbackResult = evts[i].apply(this, a);
		result = result && (callbackResult != false);
	}

	return result;
}


function ctxFunction(obj, fn, args)
{
	return function() { var a = args||[]; var a2 = shiftargs(arguments, a);  return fn.apply(obj, a2) };
}
function ctxFunction2(obj, fn, args)
{
	return function() { if(arguments.length) alert(arguments[0]); var a = args||[]; var a2 = 
shiftargs(arguments, a);  return fn.apply(obj, a2) };
}

function shiftargs(a1, a2)
{
	var result = [];
	for(var i=0; i<a1.length; i++)
	{
		result[i] = a1[i];
	}

	return result.concat(a2);
}

