/*------------------------------------
   Events.3.delegate
   Event Delegation for Events.3
   
   ****NOTE*********************
   	 Dependent on: Element.is()
   *****************************
   
   //Example:
   
   Events.delegate("#marketMovers", "click", {
   		 selector:"a.clickable"
   		,handler:this.notifyClick
   		,context:this
   		,data:myDataObject
   		,dynamicEvent:{
   			 type:'mouseout'
   			,handler:this.blurLink
   			,context:this
   			,data:myDataObject
   		}
   });
   
   arguments[0] - DOMElement || selector
   arguments[1] - eventType
   arguments[3] - object or array of objects with properties:
   		1. selector
   		2. handler
   		3. context
   		4. data
-------------------------------------*/



/*------------------------------------
	Delegate - 
	Object containing all our 
	delegate functionality 
-------------------------------------*/

EventManager.prototype.Delegation = {
	
	/*------------------------------------
		SuperClass - 
		EventManager Object instance
	-------------------------------------*/

	 SuperClass:null
	 
	 /*------------------------------------
		isDelegator - 
		Check to see if target Element is
		the element that has the delegation
		event assigned.
	-------------------------------------*/
	 
	,isDelegator:function( el, delegators ) {

		var len = delegators.length;

		while(len--) {
			if(el === delegators[len]) {
				return true;	
			}
		}
		return false;
	}
	
	/*------------------------------------
		prepArgs - 
	-------------------------------------*/

	,prepArgs:function( o ) {

		o.context = o.context || window;
		o.handler = String === o.handler.constructor? o.context[ o.handler ] : o.handler;

		if( o.dynamicEvent ) {

			var self = this;

			o.dynamicEvent    = this.prepArgs( o.dynamicEvent );
			o.dynamicEvent.fn = function( e, el, data ) {

				var d = o.dynamicEvent;
					d.handler.call( d.context, e, el, data );
				
				var evs = self.SuperClass.events;
				var len = evs.length;
				
				while(len--) {	/* Loop backwards b/c its more likely the event is at the end of the stack */
					
					if(evs[len].elements[0].node === el) {	/* there will always only be one element */

						evs[len].removeAll();
						evs.splice( len, 1 );
						break;
					}
				}
			}
		}
		return o;
	}
	
	/*------------------------------------
		assign - 
		Assign Event, prep arguments,
		create  function to give to 
		EventManager for delegation
		handling.
	-------------------------------------*/

	,assign:function( SuperClass, delegator, type, oArgs ) {
		
		this.SuperClass = this.SuperClass || SuperClass;
		
		delegator = Element.get(delegator) || Element.parseSelector(delegator);
		oArgs	  = Array.prototype.concat( oArgs );
		
		var len = oArgs.length;
		
		while(len--) {
			oArgs[len] = this.prepArgs( oArgs[len] );	
		}

		var self = this;
		var fn   = function(e, el, data){
			
			var target = e.getTarget();
		
			if( self.isDelegator(target, delegator) ) {
				return;
			}

			var  l = oArgs.length
				,cur;

			while(l--) {

				cur = oArgs[l];

				if(Element.is(target, cur.selector, el, true)) {

					if( cur.dynamicEvent ) {

						var de = cur.dynamicEvent;
			       		var ev = self.SuperClass.add( target, de.type, de.fn, de.context, de.data );
			       	}
			       	
					e.delegator = el;
					cur.handler.call(cur.context, e, target, cur.data);
				}
			}
		};
		
		return this.SuperClass.add( delegator, type, fn );
	}	
}

/*-----------------------------------
	delegate -
	Public method to adding
	the delegation events.
------------------------------------*/

EventManager.prototype.delegate = function( delegator, type, oArgs ) {
	
	return this.Delegation.assign( this, delegator, type, oArgs );
}