/*		VERSION:	1.6
	1.6		now uses hitClip() for hitTests
	1.5		added "target" movieClip reference to evt objects
	1.4		added "enabled" property
	1.3		added cancel() to abort the next timeout... until the mouse moves again


USAGE:
	#include "functions/detectHover.as"
	var detect = detectHover( 200 );		// recommend: 200
	
	detect.hover.of( my_mc ).then = function( evt ){};
	detect.unHover.of( my_mc ).then = function( evt ){};
	detect.hover.of( my_mc ).cancel()		// abort the current timeout... until the mouse moves again
	detect.mouseMove().then = function(){};
	
	// evt.isHovered  evt.wasHovered  = t/f
	
	onUnload = function(){
		detect.unload();
	}// onUnload()
	
	
DESCRIPTION:
	Detects when the mouse has hovered and then stopped over a relevant movieClip or component.
	Detects when the mouse has moved then stops outside of relevant movieClips.
	Detects when the mouse moves.
*/
function detectHover( hoverDelay ){
	#include "functions/hitClip.as"
	var parent = this || _this;
	var hoverWait_ms = hoverDelay || 33;
	
	var output = {};
	output.hover = {};
	output.unHover = {};
	output.enabled = true;
	var hoverEmitters = [];
	var unHoverEmitters = [];
	
	var mouseMoveReact = {};
	AsBroadcaster.initialize( mouseMoveReact );
	
	// detect when the mouse stops moving for awhile
	var react = {};
	Mouse.addListener( react );
	parent.addListener( react );
	var timeout = null;
	react.onMouseMove = function(){
		if(!output.enabled)		return;
		if(!parent._name){	react.unload();		return;		}
		if(timeout !== null)		clearTimeout( timeout );
		timeout = setTimeout(function(){
			if(!output.enabled)		return;
			if(!parent._name){	react.unload();		return;		}
			// mouse hasn't moved in awhile
			var xMouse = _root._xmouse;
			var yMouse = _root._ymouse;
			
			// announce un-hover
			for(var e=unHoverEmitters.length-1; e>=0; e--){
				// if:  mouse is over this movieClip
				var clip = unHoverEmitters[e].clip;
				if( !clip )		continue;		// abort when:  No movieClip
				if( !unHoverEmitters[e].broadcastMessage )		continue;		// abort when:  Events are impossible
				// var isHovered = clip.hitTest( xMouse, yMouse, false );
				var isHovered = hitClip( {x:xMouse,y:yMouse}, clip );
				unHoverEmitters[e].wasHovered = unHoverEmitters[e].isHovered || false;
				unHoverEmitters[e].isHovered = isHovered || false;
				if( isHovered )		continue;		// abort when:  Is hovered
				// then:  annouce that movieClip is hovered
				var evt = {
					isHovered: unHoverEmitters[e].isHovered,
					wasHovered: unHoverEmitters[e].wasHovered,
					target: clip
				}
				unHoverEmitters[e].broadcastMessage( "then", evt );
			}// for:  each emitter
			
			// announce hover
			for(var e=hoverEmitters.length-1; e>=0; e--){
				// if:  mouse is over this movieClip
				var clip = hoverEmitters[e].clip;
				if( !clip )		continue;		// abort when:  No movieClip
				if( !hoverEmitters[e].broadcastMessage )		continue;		// abort when:  Events are impossible
				// var isHovered = clip.hitTest( xMouse, yMouse, false );
				var isHovered = hitClip( {x:xMouse,y:yMouse}, clip );
				hoverEmitters[e].wasHovered = hoverEmitters[e].isHovered || false;
				hoverEmitters[e].isHovered = isHovered || false;
				if( !isHovered )		continue;		// abort when:  Not hovered
				// then:  annouce that movieClip is hovered
				var evt = {
					isHovered: hoverEmitters[e].isHovered,
					wasHovered: hoverEmitters[e].wasHovered,
					target: clip
				}
				hoverEmitters[e].broadcastMessage( "then", evt );
			}// for:  each emitter
		}, hoverWait_ms);
		
		mouseMoveReact.broadcastMessage( "then" );
	}// onMouseMove()
	
	//////////////////////
	output.hover.of = make_of( hoverEmitters );
	output.unHover.of = make_of( unHoverEmitters );
	
	function make_of( emitterList ){
		return function( clip ){
			var eventEmitter = {};
			eventEmitter.clip = clip;
			AsBroadcaster.initialize( eventEmitter );
			emitterList.push( eventEmitter );
			eventEmitter.isHovered = false;
			eventEmitter.wasHovered = false;
			eventEmitter.addListener( eventEmitter );
			eventEmitter.cancel = function(){
				if(timeout !== null)	clearTimeout( timeout );
			}
			return eventEmitter;
		}// return()
	}// make_of()
	
	//////////////////////
	react.unload = function(){
		// stop reacting when the mouse moves
		Mouse.removeListener( react );
		parent.removeListener( react );
		// stop detecting whent the mouse has stopped moving
		if(timeout !== null)		clearTimeout( stopDelay );
		
		// stop all "then" events
		// // hover
		for(var e=hoverEmitters.length-1; e>=0; e--){
			var thisEmitter = hoverEmitters[e];
			removeListeners( thisEmitter );
			delete thisEmitter.clip;
		}// for:  each emitter
		hoverEmitters = [];
		// // un-hover
		for(var e=unHoverEmitters.length-1; e>=0; e--){
			var thisEmitter = unHoverEmitters[e];
			removeListeners( thisEmitter );
			delete thisEmitter.clip;
		}// for:  each emitter
		unHoverEmitters = [];
		// // un-hover
		removeListeners( mouseMoveReact );
		
		function removeListeners( obj ){
			for(var L in obj._listeners){
				// remove events for this listener
				var thisListener = obj._listeners[L];
				obj.removeListener( thisListener );
				delete thisListener;
			}// for:  each listener
			obj._listeners = [];
		}// removeListeners()
	}// unload()
	
	react.unload = once( react.unload );
	output.unload = react.unload;
	
	
	//////////////////////
	output.mouseMove = function(){
		var react = {};
		mouseMoveReact.addListener( react );
		return react;
	}// mouseMove()
	
	
	//////////////////////
	return output;
	
	
	//////////////////////
	function once( func ){
		var done = false;
		return function () {
			return done ? void 0 : ((done = true), func.apply(this, arguments));
		}
	}// once()
}// detectHover()