/*	VERSION:  1.0

USAGE:  
	#include "functions/betterComboBoxEvents.as"
	var dropEvents = betterComboBoxEvents( my_drop );
	
	react.to( "focusOut" ).from( dropEvents ).then = hide;
	
	
EVENTS:  
	focusIn
	focusOut
	openStart
	openEnd
	closeStart
	closeEnd
	unload
	
	
ADDED EVENTS:  
	actual_focusIn
	actual_focusOut
	actual_openStart
	actual_openEnd
	actual_closeStart
	actual_closeEnd
	
	
DESCRIPTION:  
	Some events from the comboBox component are unreliable and unpredictable.
	This makes them reliable.
	
	This also adds events to anounce when the drop-list begins opening,  finishes opening,  begins closing,  and finishes closing.
	( the normal "open" and "close" events only fire when the list finishes animating )
	
	This also fixes a bug where the drop-list remains visible after the comboBox's "visible" setting is set to false.
*/
function betterComboBoxEvents( self ){
	var _this = self._parent || this;
	#include "updateOnce.as"
	#include "hitClip.as"
	#include "eventSystem3.as"
	if( !self )		return;
	
	//self.setStyle( "openDuration", 1 );		// 1 is a little more responsive than 0  (hit-detection more accurately detects when the list is closed)  (both generally work fine)
	var isFocused = false;
	var leftClick_code = 1;
	var isOpen = false;
	if( !_this.addListener )		AsBroadcaster.initialize( _this );
	var react = make_react( _this );		// param is optional
	var output = {};
	AsBroadcaster.initialize( output );
	
	
	// unload react upon self unload  (fire all "unload" events created using this react object)
	react.once().to( "unload" ).from( self ).then = react.unload;
	react.to("unload").tell( output );
	
	
	// make focusIn reliable and predictable
	react.to( "focusIn" ).from( self ).then = updateOnce( function(){
		if( self.visible !== true )				return;
		if( self.enabled !== true )				return;
		if( get_isFocused() !== true )		return;
		if( isFocused === true )					return;
		
		isFocused = true;
		var evt = {
			target: self
		}
		sendEvent( "actual_focusIn", evt, self );
		sendEvent( "focusIn", evt, output );
	} );// focusIn()
	
	
	// Make focusOut reliable and predictable
	react.to( "focusOut" ).from( self ).then = updateOnce( function(){
		// ignore if the user is currently clicking on this
		var isHovered = get_isHovered();
		var mouseIsDown = Key.isDown( leftClick_code );
		if( isHovered && mouseIsDown )		return;		// if:  clicking on the comboBox,  then abort,  because it shouldn't lose focus while being clicked on
		
		setTimeout( function(){
			if( get_isFocused() === true )		return;
			if( isFocused === false )					return;
			isFocused = false;
			var evt = {
				target: self
			}
			sendEvent( "actual_focusOut", evt, self );
			sendEvent( "focusOut", evt, output );
		}, 0 );
	} );// focusOut()
	
	
	// detect:  when the list begins to open.  (when the user clicks on the down-arrow
	react.to( "onMouseDown" ).from( Mouse ).then = function(){
		if( self.visible === false )		return;
		if( self.enabled === false )		return;
		if( isOpen === true )		return;
		
		var mouse_p = new flash.geom.Point( _root._xmouse, _root._ymouse );
		var downArrowIsClicked = hitClip( mouse_p, self.downArrow_mc );
		if( downArrowIsClicked ){
			var evt = {
				target: self
			}
			sendEvent( "actual_openStart", evt, self );
			sendEvent( "openStart", evt, output );
		}
	}// mouse press => open()
	
	
	// detect:  when the list finishes opening
	react.to( "open" ).from( self ).then = function(){
		isOpen = true;
		var evt = {
			target: self
		}
		sendEvent( "actual_openEnd", evt, self );
		sendEvent( "openEnd", evt, output );
	}// open()
	
	
	// detect:  when the list begins to close.  (when the user clicks on this component while it is open)
	react.to( "onMouseDown" ).from( Mouse ).then = function(){
		if( isOpen !== true )		return;
		var mouse_p = new flash.geom.Point( _root._xmouse, _root._ymouse );
		var isClicked = get_isHovered();
		// the list is closing
		setTimeout( function(){
			isOpen = false;
			var evt = {
				target: self
			}
			sendEvent( "actual_closeStart", evt, self );
			sendEvent( "closeStart", evt, output );
		}, 0);
	}// mouse press => close()
	
	
	// detect:  when the list finishes closing
	react.to( "close" ).from( self ).then = function(){
		var evt = {
			target: self
		}
		sendEvent( "actual_closeEnd", evt, self );
		sendEvent( "closeEnd", evt, output );
	}// close()
	
	
	//  Bug-fix:  make sure the list is closed when the component is hidden
	react.to( "hide" ).from( self ).then = function(){
		self.close();		// tell the drop-menu to hide
	}// hide()
	
	
	/////////////////////////////////////////////////////////////
	
	function get_isFocused(){
		var selfFocus_str = String( self._target ).split("/").join(".");
		var currentFocus = String( self.getFocus() );
		if( !currentFocus )		return false;
		var currentFocus_str = String( currentFocus );
		var output = Boolean( currentFocus_str.indexOf( selfFocus_str ) > -1 );
		return output;
	}//get_isFocused()
	
	
	function get_isHovered(){
		var mouse_p = new flash.geom.Point( _root._xmouse, _root._ymouse );
		// self.mask represents the area of the drop-list  (it ceases to exist when the list is absent)
		var textAreaIsHovered = hitClip( mouse_p, self );
		var listIsHovered = (hitClip( mouse_p, self.mask )  &&  isOpen);
		var isHovered = (textAreaIsHovered || listIsHovered);
		return isHovered;
	}// get_isHovered()
	/////////////////////////////////////////////////////////////
	
	return output;
}// betterComboBoxEvents()