////////////////////////////////////////////////////////////////////////////////
//
//  Licensed to the Apache Software Foundation (ASF) under one or more
//  contributor license agreements.  See the NOTICE file distributed with
//  this work for additional information regarding copyright ownership.
//  The ASF licenses this file to You under the Apache License, Version 2.0
//  (the "License"); you may not use this file except in compliance with
//  the License.  You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
//
////////////////////////////////////////////////////////////////////////////////

package spark.components.supportClasses
{
import flash.display.DisplayObject;
import flash.display.DisplayObjectContainer;
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.events.FocusEvent;
import flash.events.KeyboardEvent;
import flash.events.MouseEvent;
import flash.events.TimerEvent;
import flash.ui.Keyboard;
import flash.utils.Timer;

import mx.core.IUIComponent;
import mx.core.mx_internal;
import mx.events.FlexEvent;
import mx.events.SandboxMouseEvent;
import mx.managers.ISystemManager;

import spark.components.DropDownList;
import spark.events.DropDownEvent;

use namespace mx_internal;

/**
 *  The DropDownController class handles the mouse, keyboard, and focus
 *  interactions for an anchor button and its associated drop down. 
 *  This class is used by the drop-down components, such as DropDownList, 
 *  to handle the opening and closing of the drop down due to user interactions.
 * 
 *  @see spark.components.DropDownList
 *
 *  @langversion 3.0
 *  @playerversion Flash 10
 *  @playerversion AIR 1.5
 *  @productversion Flex 4
 */
public class DropDownController extends EventDispatcher
{
    /**
     *  Constructor.
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    public function DropDownController()
    {
        super();
    }
    
    //--------------------------------------------------------------------------
    //
    //  Variables
    //
    //--------------------------------------------------------------------------

    private var mouseIsDown:Boolean;

    //--------------------------------------------------------------------------
    //
    //  Properties
    //
    //--------------------------------------------------------------------------
    
    //----------------------------------
    //  openButton
    //----------------------------------
    
    private var _openButton:ButtonBase;
    
    /**
     *  A reference to the <code>openButton</code> skin part 
     *  of the drop-down component. 
     *         
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    public function set openButton(value:ButtonBase):void
    {
        if (_openButton === value)
            return;
        
        removeOpenTriggers();
            
        _openButton = value;
        
        if (_openButton)
        	_openButton.disableMinimumDownStateTime = true;
        
        addOpenTriggers();
        
    }
    
    /**
     *  @private 
     */
    public function get openButton():ButtonBase
    {
        return _openButton;
    }
    
    /**
     *  @private 
     */
    private var _systemManager:ISystemManager;

    /**
     *  A reference to the <code>SystemManager</code> used 
     *  for mouse tracking.  if none is specified, the controller
     *  will use the systemManager associated with the openButton.
     *         
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    public function set systemManager(value:ISystemManager):void
    {
        _systemManager = value; 
    }
    /**
     *  @private 
     */
    public function get systemManager():ISystemManager
    {
        return (_systemManager != null)?  _systemManager:
                (openButton != null)?  openButton.systemManager:
                                        null;
    }
    
    /**
     *  A list of display objects to consider part of the hit area
     *  of the drop down.  Mouse clicks within any component listed
     *  as an inclusion will not automatically close the drop down.
     *         
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    public var hitAreaAdditions:Vector.<DisplayObject>;
    
    //----------------------------------
    //  dropDown
    //----------------------------------
    
    private var _dropDown:DisplayObject;
    
    /**
     *  @private 
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    public function set dropDown(value:DisplayObject):void
    {
        if (_dropDown === value)
            return;
            
        _dropDown = value;
    }   
    
    /**
     *  @private 
     */
    public function get dropDown():DisplayObject
    {
        return _dropDown;
    }
        
    //----------------------------------
    //  isOpen
    //----------------------------------
    
    /**
     *  @private 
     */
    private var _isOpen:Boolean = false;
    
    /**
     *  Contains <code>true</code> if the drop down is open.   
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */  
    public function get isOpen():Boolean
    {
        return _isOpen;
    }
    
    //----------------------------------
    //  closeOnResize
    //----------------------------------
    
    private var _closeOnResize:Boolean = true;
    
    /**
     *  When <code>true</code>, resizing the system manager 
     *  closes the drop down.
     *  For mobile applications, you can set this property
     *  to <code>false</code> so that the drop down stays open when the 
     *  page orientation changes.
     * 
     *  @default true
     *  
     *  @langversion 3.0
     *  @playerversion AIR 3
     *  @productversion Flex 4.6
     */
    public function get closeOnResize():Boolean
    {
        return _closeOnResize;
    }
    
    /**
     *  @private 
     */
    public function set closeOnResize(value:Boolean):void
    {
        if (_closeOnResize == value)
            return;
        
        // remove existing resize listener if present
        if (isOpen)
            removeCloseOnResizeTrigger();
        
        _closeOnResize = value;
        
        addCloseOnResizeTrigger();
    }
        
    //----------------------------------
    //  rolloverOpenDelay
    //----------------------------------
    
    private var _rollOverOpenDelay:Number = Number.NaN;
    private var rollOverOpenDelayTimer:Timer;
    
    /**
     *  Specifies the delay, in milliseconds, to wait for opening the drop down 
     *  when the anchor button is rolled over.  
     *  If set to <code>NaN</code>, then the drop down opens on a click, not a rollover.
     * 
     *  @default NaN
     *         
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    public function get rollOverOpenDelay():Number
    {
        return _rollOverOpenDelay;
    }
    
    /**
     *  @private 
     */
    public function set rollOverOpenDelay(value:Number):void
    {
        if (_rollOverOpenDelay == value)
            return;
        
        removeOpenTriggers();
                    
        _rollOverOpenDelay = value;

        addOpenTriggers();
    }
        
    //--------------------------------------------------------------------------
    //
    //  Methods
    //
    //--------------------------------------------------------------------------   

    /**
     *  @private 
     *  Adds event triggers to the openButton to open the popup.
     * 
     *  <p>This is called from the openButton setter after the openButton has been set.</p>
     */ 
    private function addOpenTriggers():void
    {
        if (openButton)
        {
            if (isNaN(rollOverOpenDelay))
                openButton.addEventListener(FlexEvent.BUTTON_DOWN, openButton_buttonDownHandler);
            else
                openButton.addEventListener(MouseEvent.ROLL_OVER, openButton_rollOverHandler);
        }
    }
    
    /**
     *  @private
     *  Removes event triggers from the openButton to open the popup.
     * 
     *  <p>This is called from the openButton setter after the openButton has been set.</p>
     */ 
    private function removeOpenTriggers():void
    {
        // TODO (jszeto): Change this to be mouseDown. Figure out how to not 
        // trigger systemManager_mouseDown.
        if (openButton)
        {
            if (isNaN(rollOverOpenDelay))
                openButton.removeEventListener(FlexEvent.BUTTON_DOWN, openButton_buttonDownHandler);
            else
                openButton.removeEventListener(MouseEvent.ROLL_OVER, openButton_rollOverHandler);
        }
    }
    
    /**
     *  @private
     *  Adds event triggers close the popup.
     * 
     *  <p>This is called when the drop down is popped up.</p>
     */ 
    private function addCloseTriggers():void
    {
        if (systemManager)
        {
            if (isNaN(rollOverOpenDelay))
            {
                systemManager.getSandboxRoot().addEventListener(MouseEvent.MOUSE_DOWN, systemManager_mouseDownHandler);
                systemManager.getSandboxRoot().addEventListener(SandboxMouseEvent.MOUSE_DOWN_SOMEWHERE, systemManager_mouseDownHandler);
                systemManager.getSandboxRoot().addEventListener(MouseEvent.MOUSE_UP, systemManager_mouseUpHandler_noRollOverOpenDelay);
            }
            else
            {
                systemManager.getSandboxRoot().addEventListener(MouseEvent.MOUSE_MOVE, systemManager_mouseMoveHandler);
                systemManager.getSandboxRoot().addEventListener(SandboxMouseEvent.MOUSE_MOVE_SOMEWHERE, systemManager_mouseMoveHandler);
                // MOUSEUP triggers may be added in systemManager_mouseMoveHandler
            }
            
            addCloseOnResizeTrigger();
            
            if (openButton && openButton.systemManager)
                openButton.systemManager.getSandboxRoot().addEventListener(MouseEvent.MOUSE_WHEEL, systemManager_mouseWheelHandler);
        }
    }
    
    private function addCloseOnResizeTrigger():void
    {
        if (closeOnResize)
            systemManager.getSandboxRoot().addEventListener(Event.RESIZE, systemManager_resizeHandler, false, 0, true);
    }
    
    /**
     *  @private
     *  Adds event triggers close the popup.
     * 
     *  <p>This is called when the drop down is closed.</p>
     */ 
    private function removeCloseTriggers():void
    {
        if (systemManager)
        {
            if (isNaN(rollOverOpenDelay))
            {
                systemManager.getSandboxRoot().removeEventListener(MouseEvent.MOUSE_DOWN, systemManager_mouseDownHandler);
                systemManager.getSandboxRoot().removeEventListener(SandboxMouseEvent.MOUSE_DOWN_SOMEWHERE, systemManager_mouseDownHandler);
                systemManager.getSandboxRoot().removeEventListener(MouseEvent.MOUSE_UP, systemManager_mouseUpHandler_noRollOverOpenDelay);
            }
            else
            {
                systemManager.getSandboxRoot().removeEventListener(MouseEvent.MOUSE_MOVE, systemManager_mouseMoveHandler);
                systemManager.getSandboxRoot().removeEventListener(SandboxMouseEvent.MOUSE_MOVE_SOMEWHERE, systemManager_mouseMoveHandler);
                systemManager.getSandboxRoot().removeEventListener(MouseEvent.MOUSE_UP, systemManager_mouseUpHandler);
                systemManager.getSandboxRoot().removeEventListener(SandboxMouseEvent.MOUSE_UP_SOMEWHERE, systemManager_mouseUpHandler);
            }
            
            removeCloseOnResizeTrigger();
            
            if (openButton && openButton.systemManager)
                openButton.systemManager.getSandboxRoot().removeEventListener(MouseEvent.MOUSE_WHEEL, systemManager_mouseWheelHandler);
        }
    } 
    
    private function removeCloseOnResizeTrigger():void
    {
        if (closeOnResize)
            systemManager.getSandboxRoot().removeEventListener(Event.RESIZE, systemManager_resizeHandler);
    }
    
    /**
     *  @private
     *  Helper method for the mouseMove and mouseUp handlers to see if 
     *  the mouse is over a "valid" region.  This is used to help determine 
     *  when the dropdown should be closed.
     */ 
    private function isTargetOverDropDownOrOpenButton(target:DisplayObject):Boolean
    {
        if (target)
        {
            // check if the target is the openButton or contained within the openButton
            if (openButton && openButton.contains(target))
                return true;
            if (hitAreaAdditions != null)
            {
                for (var i:int = 0;i<hitAreaAdditions.length;i++)
                {
                    if (hitAreaAdditions[i] == target ||
                        ((hitAreaAdditions[i] is DisplayObjectContainer) && DisplayObjectContainer(hitAreaAdditions[i]).contains(target as DisplayObject)))
                        return true;
                }
            }
            
            // check if the target is the dropdown or contained within the dropdown
            if (dropDown is DisplayObjectContainer)
            {
                if (DisplayObjectContainer(dropDown).contains(target))
                    return true;
            }
            else
            {
                if (target == dropDown)
                    return true;
            }
        }
        
        return false;
    }

    /**
     *  Open the drop down and dispatch a <code>DropdownEvent.OPEN</code> event. 
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */ 
    public function openDropDown():void
    {
        openDropDownHelper(true);
    }   
    
    /**
     *  @private
     *  Set isProgrammatic to true if you are opening the dropDown programmatically 
     *  or not through a mouse click or rollover.  
     */ 
    private function openDropDownHelper(isProgrammatic:Boolean = false):void
    {
        if (!isOpen)
        {
            addCloseTriggers();
            
            _isOpen = true;
            // Force the button to stay in the down state
            if (openButton)
                openButton.keepDown(true, !isProgrammatic); 
            
            dispatchEvent(new DropDownEvent(DropDownEvent.OPEN));
        }
    }
    
    /**
     *  Close the drop down and dispatch a <code>DropDownEvent.CLOSE</code> event.  
     *   
     *  @param commit If <code>true</code>, commit the selected
     *  data item. 
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    public function closeDropDown(commit:Boolean):void
    {
        if (isOpen)
        {   
            _isOpen = false;
            if (openButton)
                openButton.keepDown(false);
            
            var dde:DropDownEvent = new DropDownEvent(DropDownEvent.CLOSE, false, true);
            
            if (!commit)
                dde.preventDefault();
            
            dispatchEvent(dde);
            
            removeCloseTriggers();
        }
    }   
        
    //--------------------------------------------------------------------------
    //
    //  Event handling
    //
    //--------------------------------------------------------------------------
    
     /**
     *  @private
     *  Called when the buttonDown event is dispatched. This function opens or closes
     *  the dropDown depending upon the dropDown state. 
     */ 
    mx_internal function openButton_buttonDownHandler(event:Event):void
    {
        if (isOpen)
            closeDropDown(true);
        else
        {
            mouseIsDown = true;
            openDropDownHelper();
        }
    }
            
    /**
     *  @private
     *  Called when the openButton's <code>rollOver</code> event is dispatched. This function opens 
     *  the drop down, or opens the drop down after the length of time specified by the 
     *  <code>rollOverOpenDelay</code> property.
     */ 
    mx_internal function openButton_rollOverHandler(event:MouseEvent):void
    {
        if (rollOverOpenDelay == 0)
            openDropDownHelper();
        else
        {
            openButton.addEventListener(MouseEvent.ROLL_OUT, openButton_rollOutHandler);
            rollOverOpenDelayTimer = new Timer(rollOverOpenDelay, 1);
            rollOverOpenDelayTimer.addEventListener(TimerEvent.TIMER_COMPLETE, rollOverDelay_timerCompleteHandler);
            rollOverOpenDelayTimer.start();
        }
    }
    
    /**
     *  @private 
     *  Called when the openButton's rollOut event is dispatched while waiting 
     *  for the rollOverOpenDelay. This will cancel the timer so we don't open
     *  any more.
     */ 
    private function openButton_rollOutHandler(event:MouseEvent):void
    {
        if (rollOverOpenDelayTimer && rollOverOpenDelayTimer.running)
        {
            rollOverOpenDelayTimer.stop();
            rollOverOpenDelayTimer = null;
        }
        
        openButton.removeEventListener(MouseEvent.ROLL_OUT, openButton_rollOutHandler);
    }
    
    /**
     *  @private
     *  Called when the rollOverDelay Timer is up and we should show the drop down.
     */ 
     private function rollOverDelay_timerCompleteHandler(event:TimerEvent):void
     {
         openButton.removeEventListener(MouseEvent.ROLL_OUT, openButton_rollOutHandler);
         rollOverOpenDelayTimer = null;
         
         openDropDownHelper();
     }
            
    /**
     *  @private
     *  Called when the systemManager receives a mouseDown event. This closes
     *  the dropDown if the target is outside of the dropDown. 
     */     
    mx_internal function systemManager_mouseDownHandler(event:Event):void
    {
        // stop here if mouse was down from being down on the open button
        if (mouseIsDown)
        {
            mouseIsDown = false;
            return;
        }

        if (!dropDown || 
            (dropDown && 
             (event.target == dropDown 
             || (dropDown is DisplayObjectContainer && 
                 !DisplayObjectContainer(dropDown).contains(DisplayObject(event.target))))))
        {
            // don't close if it's on the openButton
            var target:DisplayObject = event.target as DisplayObject;
            if (openButton && target && openButton.contains(target))
                return;
			
			// don't close if something just been selected in a DropDownList
			if (target is IUIComponent)
			{
                var document:Object = (target as IUIComponent).document;
                if (("hostComponent" in document) && document.hostComponent is DropDownList)
			        return;
            }

            if (hitAreaAdditions != null)
            {
				var length:int = hitAreaAdditions.length;
                for (var i:int = 0;i < length; i++)
                {
                    if (hitAreaAdditions[i] == target ||
                        ((hitAreaAdditions[i] is DisplayObjectContainer) && DisplayObjectContainer(hitAreaAdditions[i]).contains(target)))
                        return;
                }
            }

			// contains() doesn't cover popups/dropdowns, but owns() does.
			if (dropDown is IUIComponent)
			{
				if ((dropDown as IUIComponent).owns(target))
					return;
			}
            closeDropDown(true);
        } 
    }
    
    /**
     *  @private
     *  Called when the dropdown is popped up from a rollover and the mouse moves 
     *  anywhere on the screen.  If the mouse moves over the openButton or the dropdown, 
     *  the popup will stay open.  Otherwise, the popup will close.
     */ 
    mx_internal function systemManager_mouseMoveHandler(event:Event):void
    {
        var target:DisplayObject = event.target as DisplayObject;
        var containedTarget:Boolean = isTargetOverDropDownOrOpenButton(target);
        
        if (containedTarget)
            return;
        
        // if the mouse is down, wait until it's released to close the drop down
        if ((event is MouseEvent && MouseEvent(event).buttonDown) ||
            (event is SandboxMouseEvent && SandboxMouseEvent(event).buttonDown))
        {
            systemManager.getSandboxRoot().addEventListener(MouseEvent.MOUSE_UP, systemManager_mouseUpHandler);
            systemManager.getSandboxRoot().addEventListener(SandboxMouseEvent.MOUSE_UP_SOMEWHERE, systemManager_mouseUpHandler);
            return;
        }
        
        closeDropDown(true);
    }
    
    /**
     *  @private
     *  Debounce the mouse
     */
    mx_internal function systemManager_mouseUpHandler_noRollOverOpenDelay(event:Event):void
    {
        // stop here if mouse was down from being down on the open button
        if (mouseIsDown)
        {
            mouseIsDown = false;
            return;
        }
    }

    /**
     *  @private
     *  Called when the dropdown is popped up from a rollover and the mouse is released 
     *  anywhere on the screen.  This will close the popup.
     */ 
    mx_internal function systemManager_mouseUpHandler(event:Event):void
    {
        var target:DisplayObject = event.target as DisplayObject;
        var containedTarget:Boolean = isTargetOverDropDownOrOpenButton(target);

        // if we're back over the target area, remove this event listener
        // and do nothing.  we handle this in mouseMoveHandler()
        if (containedTarget)
        {
            systemManager.getSandboxRoot().removeEventListener(MouseEvent.MOUSE_UP, systemManager_mouseUpHandler);
            systemManager.getSandboxRoot().removeEventListener(SandboxMouseEvent.MOUSE_UP_SOMEWHERE, systemManager_mouseUpHandler);
            return;
        }
        
        closeDropDown(true);
    }
    
    /**
     *  @private
     *  Close the dropDown if the stage has been resized.
     */
    mx_internal function systemManager_resizeHandler(event:Event):void
    {
        closeDropDown(true);
    }       
    
    /**
     *  @private
     *  Called when the mouseWheel is used
     */
    private function systemManager_mouseWheelHandler(event:MouseEvent):void
    {
        // Close the dropDown unless we scrolled over the dropdown and the dropdown handled the event
        if (dropDown && !(DisplayObjectContainer(dropDown).contains(DisplayObject(event.target)) && event.isDefaultPrevented()))
            closeDropDown(false);
    }
    
    /**
     *  Close the drop down if it is no longer in focus.
     *
     *  @param event The event object for the <code>FOCUS_OUT</code> event.
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    public function processFocusOut(event:FocusEvent):void
    {
        // Note: event.relatedObject is the object getting focus.
        // It can be null in some cases, such as when you open
        // the dropdown and then click outside the application.
        
        // If the dropdown is open...
        if (isOpen)
        {
            // If focus is moving outside the dropdown...
            if (!event.relatedObject ||
                (!dropDown || 
                    (dropDown is DisplayObjectContainer &&
                     !DisplayObjectContainer(dropDown).contains(event.relatedObject))))
            {
                // Close the dropdown.
                closeDropDown(true);
            }
        }
    }
    
    /**
     *  Handles the keyboard user interactions.
     *
     *  @param event The event object from the keyboard event.
     * 
     *  @return Returns <code>true</code> if the <code>keyCode</code> was 
     *  recognized and handled.
     * 
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4 
     */
    public function processKeyDown(event:KeyboardEvent):Boolean
    {
        
        if (event.isDefaultPrevented())
            return true;
        
        if (event.ctrlKey && event.keyCode == Keyboard.DOWN)
        {
            openDropDownHelper(true); // Programmatically open
            event.preventDefault();
        }
        else if (event.ctrlKey && event.keyCode == Keyboard.UP)
        {
            closeDropDown(true);
            event.preventDefault();
        }    
        else if (event.keyCode == Keyboard.ENTER)
        {
            // Close the dropDown and eat the event if appropriate.
            if (isOpen)
            {
                closeDropDown(true);
                event.preventDefault();
            }
        }
        else if (event.keyCode == Keyboard.ESCAPE)
        {
            // Close the dropDown and eat the event if appropriate.
            if (isOpen)
            {
                closeDropDown(false);
                event.preventDefault();
            }
        }
        else
        {
            return false;
        }   
            
        return true;        
    }
                
}
}
