/**
 * @author Artur
 */
var EventManager =
{
	_listeners : [],
	
	addListener : function (obj1, obj2)
	{
		if (obj1 != undefined && obj1 != null) 
		{
			if (this._listeners == undefined) 
			{
				this._listeners = [];
			}
			var evl;
			for (var eventz in obj2) 
			{
				evl = new EventListener(obj1, undefined, obj2, eventz);
				if (this._listeners[obj1] == undefined) 
				{
					this._listeners[obj1] = [];
				}
				this._listeners[obj1].push(evl);
				obj1[eventz] = Delegate(this, this._inLineDispatchEvent, [evl]);
			}
		}
	},
	
	removeListener : function (obj1, obj2)
	{
		for (var i = 0; i < this._listeners[obj1].length; i ++)
		{
			for(var eventz in obj2)
			{		
				var lst = this._listeners[obj1][i];
				if (lst.obj1 == obj1 && lst.obj2 == obj2 && lst.eventz == eventz)
				{
					ArrayUtil.remove(this._listeners[obj1], lst);
				}
				delete lst;
			}
		}
	},
	
	//Método "Dispatcher" utilizado para chamadas sob-demanda
	//Normalmente esse método é utilizado para disparar eventos de uma classe
	//para seu "mundo exterior".  
	_dispatchEvent : function ()
	{
		var evlFrom;
		var arrArgs = [];
		var arrArgsX = [];
		
		var arrBuffer = [];
		
		evlFrom = arguments[0];
	
		var s = evlFrom.args.length;
		
		for (var i = 0; i < s; i ++)
		{
			arrBuffer.push(evlFrom.args[i]);
		}
		
		delete arrBuffer;
		
		//Monta um array com os argumentos passados para a função
		//Nessa montagem sempre é inserido o objeto do EventListener
		//como primeiro argumento 
		evlFrom.args = [evlFrom];
		evlFrom.args = evlFrom.args.concat(arrBuffer);
	
		if (this._listeners[evlFrom.obj1] != undefined)
		{
			for (var i = 0; i < this._listeners[evlFrom.obj1].length; i ++)
			{
				var evl = this._listeners[evlFrom.obj1][i];
				if (evl.obj1 == evlFrom.obj1 && evl.eventz == evlFrom.eventz)
				{
					evl.obj2[evl.eventz].apply(evlFrom.scope, evlFrom.args);
				}
			}
		}
	},
	
	//Método "Dispatcher" que é inserido nos eventos das tags HTML 
	_inLineDispatchEvent : function ()
	{
		var evlFrom;
		var arrArgs = [];
		var arrArgsX = [];
		
		if (browserType() == "ie")
		{
			evlFrom = arguments[0];
		}
		else
		{
			evlFrom = arguments[0 + (arguments[0] instanceof Event ? 1 : 0)];
		}

		evlFrom.args = [];
		if (browserType() == "ie")
		{
			evlFrom.args.push(window.event);
		}
		for (var i = 0; i < arguments.length; i ++)
		{
			evlFrom.args.push(arguments[i]);
		}
		
		if (this._listeners[evlFrom.obj1] != undefined)
		{
			for (var i = 0; i < this._listeners[evlFrom.obj1].length; i ++)
			{
				var evl = this._listeners[evlFrom.obj1][i];
				if (evl.obj1 == evlFrom.obj1 && evl.eventz == evlFrom.eventz)
				{
					evl.obj2[evl.eventz].apply(evlFrom.scope, evlFrom.args);
				}
			}
		}
	}
}

function EventListener(obj1, scope, obj2, eventz, args)
{
	this.obj1 = obj1;
	this.scope = scope;
	this.obj2 = obj2;
	this.eventz = eventz;
	this.args = args;
	
	this.toString = function()
	{
		return "{obj1=" + this.obj1 + ",event=" + this.eventz + "}";
	}
}


function EventDispatcher(scope, evnt)
{
	this.scope = scope;
	this.evnt = evnt;
	
	this.dispatch = Delegate(this, function()
	{
		EventManager._dispatchEvent(new EventListener(this.scope, undefined, this.scope, this.evnt, arguments));
	});
}
