var Events = {};
Events.objects = {};
// PUBLIC

/**
* addEvent
* 
* objName - String
* eventName - String
* method - Function
* 
* return id - Number - the id coresponding to added method
* */
Events.addEvent = function(objName, eventName, method){
	if(!this.getRealObj(objName)) return null;
	var eObj = this.getEventObj(objName, eventName);
	var id = eObj.ids++;
	eObj.methods.push({ id:id, method:method });
	return id;
};
/**
* removeEvent
* 
* objName - String
* eventName - String
* id - Number
* */
Events.removeEvent = function(objName, eventName, id){
	var eObj = this.getEventObj(objName, eventName);
	for(var i=0; i < eObj.methods.length; i++){
		if(id == eObj.methods[i].id){
			eObj.methods.splice(i, 1);
			if(!eObj.methods.length){
				var rObj = this.getRealObj(objName);
				var obj = this.getObj(objName);
				// remove event
				rObj[eventName] = null;
				obj[eventName] = null;
				// remove object if no other events
				var haveEvents = false;
				for(var evt in obj){
					if(obj[evt] != null){
						haveEvents = true;
						break;
					}
				}
				if(!haveEvents){
					this.removeObj(objName);
				}
			}
			break;
		}
	}
};
/**
* setReturnValue - useful for onclick
* 
* objName - String
* eventName - String
* value - *
* */
Events.setReturnValue = function(objName, eventName, value){
	var eObj = this.getEventObj(objName, eventName);
	eObj.returnValue = value;
};
/**
* removeObj
* 
* objName - String
* */
Events.removeObj = function(objName){
	var rObj = this.getRealObj(objName);
	var obj = this.getObj(objName);
	if(this.objects[objName]){
		for(var evt in obj){
			rObj[evt] = null;
		}
		this.objects[objName] = null;
	}
};
/**
* removeAll
* 
* */
Events.removeAll = function(){
	for(var objName in this.objects){
		this.removeObj(objName);
	}
};

// PRIVATE
Events.getRealObj = function(objName){
	if(util.element(objName)) return util.element(objName);
	return eval(objName);
};
Events.getObj = function(objName){
	if(!this.objects[objName]) this.objects[objName] = {};
	return this.objects[objName];
};
Events.getEventObj = function(objName, eventName){
	var obj = this.getObj(objName);
	if(!obj[eventName]){
		obj[eventName] = { ids:0, methods:[], returnValue:null };
		this.getRealObj(objName)[eventName] = Delegate.create(this, this.callEvent, objName, eventName);
	}
	return obj[eventName];
};
Events.checkObj = function(objName, eventName){
	if(!this.getEventObj(objName, eventName).methods.length){
		var rObj = this.getRealObj(objName);
		var obj = this.getObj(objName);
		// remove event
		rObj[eventName] = null;
		obj[eventName] = null;
		// remove object if no other events
		var haveEvents = false;
		for(var evt in obj){
			if(obj[evt] != null){
				haveEvents = true;
				break;
			}
		}
		if(!haveEvents){
			this.removeObj(objName);
		}
	}
};
Events.callEvent = function(objName, eventName){
	var eObj = this.getEventObj(objName, eventName);
	var rObj = this.getRealObj(objName);
	var args = util.copyArray(arguments).slice(2);
	for(var i=0; i < eObj.methods.length; i++){
		eObj.methods[i].method.apply(rObj ,args);
	}
	return typeof(eObj.returnValue) == "function" ? eObj.returnValue() : eObj.returnValue;
};

Events.setReturnValue("window", "onunload", function(){ Events.removeAll(); });