/*##events*/
function LynxEventObject(object){
	this.object = object;
}

LynxEventObject.prototype.addEvent = function(type,func,name){
	var out = false;
	var t = this[type];
	if(!t){
		t = (this[type]=new Array());
		out = true;
	}
	if(name!=undefined){
		var id = type+'-'+name;
		if(this[id]==undefined)this[id]=t.length;
		t[this[id]] = func;
	}else t[t.length] = func;
	return out;
}

LynxEventObject.prototype.removeEvent = function(type,func,name){
	var t = this[type];
	if(!t)return;
	if(name!=undefined){
		var id = type+'-'+name;
		if(this[id]==undefined)return;
		if(func!=undefined && t[this[id]]!=func)return;
		t.splice(this[id],1);
		delete this[id];
		return;
	}else for(var i=0,len=t.length;i<len;++i)if(t[i]==func){t.splice(i,1);return;}
	return !(t.length);
}

LynxEventObject.prototype.callEvent = function(type,event,args){
	var t = this[type];
	if(!t)return;
	args.unshift(event);
	if(!event.stopPropagation)event.stopPropagation = function(){event.cancelBubble=true};
	for(var i=0,len=t.length;i<len;++i)t[i].apply(this.object,args);
}

LynxEventObject.prototype.free = function(){
	this.object = null;
}

function LynxEventManager(gc){
	this.objects = new Array();
	if(gc!=undefined){
		gc.add(this);
		this.addUnload(function(){gc.collect()});
	}
}

LynxEventManager.prototype.addEvent = function(object,type,func,name){
	var leo = this.getObject(object);
	if(!leo){
		leo = new LynxEventObject(object);
		this.objects.push(leo);
	}
	if(leo.addEvent(type,func,name))this._registerEvent(leo,type);
}

LynxEventManager.prototype.removeEvent = function(object,type,func,name){
	var leo = this.getObject(object);
	if(!leo)return;
	if(leo.removeEvent(type,func,name))this._unregisterEvent(leo,type);
}

LynxEventManager.prototype.callEvent = function(leo,type,event){
	var args = new Array();
	event = event||window.event;
	for(var i=3; i<arguments.length; i++)args[i-3]=arguments[i];
	leo.callEvent(type,event,args);
}

LynxEventManager.prototype.removeObject = function(object){
	var leo = this.getObject(object);
	if(!leo)return;
	leo.free();
	var objs = this.objects;
	for(var i=0,len=objs.length;i<len;++i)if(objs[i]==leo){objs.splice(i,1);return;}
}

LynxEventManager.prototype.getObject = function(object){
	var objs = this.objects;
	for(var i=0,ei;ei=objs[i];++i)if(ei.object === object)return ei;
	return null;
}

LynxEventManager.prototype.addLoad = function(func){
	this.addEvent(window,'load',func);
}

LynxEventManager.prototype.addUnload = function(func){
	this.addEvent(window,'unload',func);
}

LynxEventManager.prototype.free = function(){
	var objs = this.objects;
	for(var i=0,ei;ei=objs[i];++i)ei.free();
	this.objects = null;
}

LynxEventManager.prototype._registerEvent = function(leo,type){
	var _me = this;
	leo.object['on'+type] = function(event){_me.callEvent(leo,type,event);return false};
}

LynxEventManager.prototype._unregisterEvent = function(leo,type){
	leo.object['on'+type] = null;
}

/*#@init*/
var LEM = new LynxEventManager(GC);
