////////////////////////////////////////////////////////////////////////////////
//
//  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.BlendMode;
import flash.display.Graphics;
import flash.events.Event;
import flash.events.FocusEvent;
import flash.events.KeyboardEvent;
import flash.events.MouseEvent;
import flash.geom.Rectangle;
import flash.ui.ContextMenu;
import flash.ui.Keyboard;

import mx.core.mx_internal;
import mx.events.SandboxMouseEvent;
import mx.styles.IStyleClient;

import spark.components.RichEditableText;
import spark.components.TextSelectionHighlighting;

import flashx.textLayout.tlf_internal;
import flashx.textLayout.container.ContainerController;
import flashx.textLayout.container.TextContainerManager;
import flashx.textLayout.edit.EditManager;
import flashx.textLayout.edit.EditingMode;
import flashx.textLayout.edit.ElementRange;
import flashx.textLayout.edit.IEditManager;
import flashx.textLayout.edit.ISelectionManager;
import flashx.textLayout.edit.SelectionFormat;
import flashx.textLayout.edit.SelectionManager;
import flashx.textLayout.edit.SelectionState;
import flashx.textLayout.elements.FlowLeafElement;
import flashx.textLayout.elements.IConfiguration;
import flashx.textLayout.elements.ParagraphElement;
import flashx.textLayout.elements.TextFlow;
import flashx.textLayout.elements.TextRange;
import flashx.textLayout.events.SelectionEvent;
import flashx.textLayout.formats.Category;
import flashx.textLayout.formats.ITextLayoutFormat;
import flashx.textLayout.formats.TextLayoutFormat;
import flashx.textLayout.operations.ApplyFormatOperation;
import flashx.textLayout.operations.InsertTextOperation;
import flashx.textLayout.property.Property;
import flashx.undo.IUndoManager;
import flashx.undo.UndoManager;

use namespace mx_internal;
use namespace tlf_internal;

[ExcludeClass]

/**
 *  @private
 *  A subclass of TextContainerManager that manages the text in
 *  a RichEditableText component.
 *  
 *  @langversion 3.0
 *  @playerversion Flash 10
 *  @playerversion AIR 1.5
 *  @productversion Flex 4
 */
public class RichEditableTextContainerManager extends TextContainerManager
{
	//--------------------------------------------------------------------------
	//
	//  Class Variables
	//
	//--------------------------------------------------------------------------
	/**
	 *  @private
	 *  Disables blinking cursor so mustella test snapshots don't get intermittent
	 *  cursors.
	 */
	mx_internal static var hideCursor:Boolean = false;
	
    /**
     *  Constructor. 
     *  
     *  @langversion 3.0
     *  @playerversion Flash 10
     *  @playerversion AIR 1.5
     *  @productversion Flex 4
     */
    public function RichEditableTextContainerManager(
                        container:RichEditableText, 
                        configuration:IConfiguration=null)
    {
        super(container, configuration);

        textDisplay = container;
    }

    //--------------------------------------------------------------------------
    //
    //  Variables
    //
    //--------------------------------------------------------------------------

    /**
     *  @private
     */
    private var hasScrollRect:Boolean = false;

    /**
     *  @private
     */
    private var textDisplay:RichEditableText;

    //--------------------------------------------------------------------------
    //
    //  Overridden methods
    //
    //--------------------------------------------------------------------------
        
    /**
     *  @private
     */
    override public function drawBackgroundAndSetScrollRect(
                                    scrollX:Number, scrollY:Number):Boolean
    {
        // If not auto-sizing these are the same as the compositionWidth/Height.
        // If auto-sizing, the compositionWidth/Height may be NaN.  If no
        // constraints this will reflect the actual size of the text.
        var width:Number = textDisplay.width;
        var height:Number = textDisplay.height;
        
        var contentBounds:Rectangle = getContentBounds();
        
        // If measuring width, use the content width.
        if (isNaN(width))
            width = contentBounds.right;
        
        // If measuring height, use the content height.
        if (isNaN(height))
            height = contentBounds.bottom;

        // TODO:(cframpto)  Adjust for RL text.  
        // See ContainerController.updateVisibleRectangle().
        // (effectiveBlockProgression == BlockProgression.RL) ? -width : 0;
        var xOrigin:Number = 0;

        // If autoSize, and lineBreak="toFit" there should never be 
        // a scroll rect but if lineBreak="explicit" the text may need
        // to be clipped.
        if (scrollX == 0 && scrollY == 0 &&
            contentBounds.left >= xOrigin &&
            contentBounds.right <= width &&
            contentBounds.top >= 0 &&
            contentBounds.bottom <= height)
        {
            // skip the scrollRect
            if (hasScrollRect)
            {
                container.scrollRect = null;
                hasScrollRect = false;                  
            }
        }
        else
        {
            container.scrollRect = new Rectangle(scrollX, scrollY, width, height);
            hasScrollRect = true;
        }
        
        // Client must draw a background to get mouse events,
        // even it if is 100% transparent.
    	// If backgroundColor is defined, fill the bounds of the component
    	// with backgroundColor drawn with alpha level backgroundAlpha.
    	// Otherwise, fill with transparent black.
    	// (The color in this case is irrelevant.)
    	var color:uint = 0x000000;
    	var alpha:Number = 0.0;
    	var styleableContainer:IStyleClient = container as IStyleClient;
    	if (styleableContainer)
    	{
    		var backgroundColor:* =
    			styleableContainer.getStyle("backgroundColor");
    		if (backgroundColor !== undefined)
    		{
    			color = uint(backgroundColor);
    			alpha = styleableContainer.getStyle("backgroundAlpha");
    		}
    	}
        // TODO (cframpto):  Adjust for RL text.  See 
        // ContainerController.attachTransparentBackgroundForHit().
        var g:Graphics = container.graphics;
        g.clear();
        g.lineStyle();
        g.beginFill(color, alpha);
        g.drawRect(scrollX, scrollY, width, height);
        g.endFill();
        
        return hasScrollRect;
    }
        
    /**
     *  @private
     * 
     * If the user specified a custom context menu then use
     * it rather than the default context menu. It must be set before the
     * first mouse over/mouse hover or foucsIn event to be used.
     * 
     * TLF will remove the context menu when it switches from the factory
     * to the composer and the controller will then request it again.
     */
    override tlf_internal function getContextMenu():ContextMenu
    {
        // ToDo(cframpto): Ideally could specify the context
        // menu on the TextArea or the TextInput and it wouldn't be obscured
        // by TLF's context menu.

        // Return null to use the existing contextMenu on the container.
        // Otherwise the TCM will overwrite this contextMenu.
        return textDisplay.contextMenu != null ? null : super.getContextMenu();
    }
    
    /**
     *  @private
     */
    override protected function getUndoManager():IUndoManager
    {
        if (!textDisplay.undoManager)
        {
            textDisplay.undoManager = new UndoManager();
            textDisplay.undoManager.undoAndRedoItemLimit = int.MAX_VALUE;
        }
            
        return textDisplay.undoManager;
    }
    
    /**
     *  @private
     */
    override protected function getFocusedSelectionFormat():SelectionFormat
    {
        var selectionColor:* = textDisplay.getStyle("focusedTextSelectionColor");

        var focusedPointAlpha:Number =
            editingMode == EditingMode.READ_WRITE ?
            1.0 :
            0.0;

        // If editable, the insertion point is black, inverted, which makes it
        // the inverse color of the background, for maximum readability.         
        // If not editable, then no insertion point.        
        return new SelectionFormat(
            selectionColor, 1.0, BlendMode.NORMAL, 
            0x000000, hideCursor ? 0 : focusedPointAlpha, BlendMode.INVERT);
    }
    
    /**
     *  @private
     */
    override protected function getUnfocusedSelectionFormat():SelectionFormat
    {
        var unfocusedSelectionColor:* = textDisplay.getStyle(
                                            "unfocusedTextSelectionColor");

        var unfocusedAlpha:Number =
            textDisplay.selectionHighlighting != 
            TextSelectionHighlighting.WHEN_FOCUSED ?
            1.0 :
            0.0;

        // No insertion point when no focus.
        return new SelectionFormat(
            unfocusedSelectionColor, unfocusedAlpha, BlendMode.NORMAL,
            unfocusedSelectionColor, 0.0);
    }
    
    /**
     *  @private
     */
    override protected function getInactiveSelectionFormat():SelectionFormat
    {
        var inactiveSelectionColor:* = textDisplay.getStyle(
                                            "inactiveTextSelectionColor"); 

        var inactivePointAlpha:Number = 0.0;
        
        var inactiveRangeAlpha:Number =
            textDisplay.selectionHighlighting == 
            TextSelectionHighlighting.ALWAYS ?
            1.0 :
            0.0;

        
        // This doesn't really matter since inactivePointAlpha is 0.
        var pointBlinkRate:Number = 0.0;
        
        return new SelectionFormat(
            inactiveSelectionColor, inactiveRangeAlpha, BlendMode.NORMAL,
            inactiveSelectionColor, inactivePointAlpha, BlendMode.INVERT,
            pointBlinkRate);
    }   
    
    /**
     *  @private
     */
    override protected function createEditManager(
                        undoManager:flashx.undo.IUndoManager):IEditManager
    {
        var editManager:IEditManager = super.createEditManager(undoManager);
        
        // Default is to batch text input.  If the component, like ComboBox
        // wants to act on each keystroke then set this to false.
        editManager.allowDelayedOperations = textDisplay.batchTextInput;
        
        // Do not delayUpdates until further work is done to ensure our public API methods to
        // format and insert text work correctly.  TLF does not dispatch the selectionChange
        // event until the display is updated which means our selection properties may not
        // be in sync with the TLF values. This could matter for our API methods that
        // take the selection as parameters or default to the current selection.  In the
        // former case, the user could query for the selection or rely on the selectionChange
        // event and get incorrect values if there is a pending update and in the later case 
        // we fill in the default selection which might not be current if there is a pending 
        // update.
        editManager.delayUpdates = false;
        
        return editManager;
    }

    /**
     *  @private
     */
    override public function setText(text:String):void
    {
        super.setText(text);
        
        // If we have focus, need to make sure we can still input text.
        initForInputIfHaveFocus();
    }

    /**
     *  @private
     */
    override public function setTextFlow(textFlow:TextFlow):void
    {
        super.setTextFlow(textFlow);
        
        // If we have focus, need to make sure we can still input text.
        initForInputIfHaveFocus();
    }

    /**
     *  @private
     */
    private function initForInputIfHaveFocus():void
    {
        // If we have focus, need to make sure there is a composer in place,
        // the new controller knows it has focus, and there is an insertion
        // point so input works without a mouse over or mouse click.  Normally 
        // this is done in our focusIn handler by making sure there is a 
        // selection.  Test this by clicking an arrow in the NumericStepper 
        // and then entering a number without clicking on the input field first. 
        if (editingMode != EditingMode.READ_ONLY &&
            textDisplay.getFocus() == textDisplay)
        {
            // this will ensure a text flow with a comopser
            var im:ISelectionManager = beginInteraction();
            
            var controller:ContainerController = 
                getTextFlow().flowComposer.getControllerAt(0);
            
            controller.requiredFocusInHandler(null);
            
            if (!preserveSelectionOnSetText)
                im.selectRange(0, 0);
            
            endInteraction();
        }
    }
    
    /**
     *  @private
     *  To apply a format to a selection in a textFlow without using the
     *  selection manager.
     */
    mx_internal function applyFormatOperation(
                            leafFormat:ITextLayoutFormat, 
                            paragraphFormat:ITextLayoutFormat, 
                            containerFormat:ITextLayoutFormat,
                            anchorPosition:int, 
                            activePosition:int):Boolean
    {
        // Nothing to do.
        if (anchorPosition == -1 || activePosition == -1)
            return true;
        
        var textFlow:TextFlow = getTextFlowWithComposer();
        
        var operationState:SelectionState =
            new SelectionState(textFlow, anchorPosition, activePosition);
                    
        // If using the edit manager and the selection is the current selection,
        // need to set the flag so point selection is set with pending formats for next 
        // char typed.
        const editManager:IEditManager = textFlow.interactionManager as IEditManager;
        if (editManager)
        {
            const absoluteStart:int = getAbsoluteStart(anchorPosition, activePosition);
            const absoluteEnd:int = getAbsoluteEnd(anchorPosition, activePosition);
            
            if (editManager.absoluteStart == absoluteStart && editManager.absoluteEnd == absoluteEnd)
                operationState.selectionManagerOperationState = true;
        }
        
        // For the case when interactive editing is not allowed.
        var op:ApplyFormatOperation = 
            new ApplyFormatOperation(
                operationState, leafFormat, paragraphFormat, containerFormat);

        var success:Boolean = op.doOperation();
        if (success)
        {
            textFlow.normalize(); 
            textFlow.flowComposer.updateAllControllers(); 
        }
        
        return success;
    }

    /**
     *  @private
     *  To get the format of a character.  Our API allows this operation even
     *  when the editingMode does not permit either interactive selection or
     *  editing.
     */
    mx_internal function getCommonCharacterFormat(
                                        anchorPosition:int, 
                                        activePosition:int):ITextLayoutFormat
    {
        if (anchorPosition == -1 || activePosition == -1)
            return null;
        
        var textFlow:TextFlow = getTextFlowWithComposer();
        
        if (textFlow.interactionManager)
        {
            // If there is a selection manager use it so that the format,
            // depending on the range, may include any attributes set on a point 
            // selection but not yet applied.	
            const range:TextRange = 
                new TextRange(textFlow, anchorPosition, activePosition);
            
            return textFlow.interactionManager.getCommonCharacterFormat(range);
        }
        else
        {
            // ElementRange will order the selection points.  Since there isn't
            // an interactionManager there is not a point selection to worry
            // about.
            var selRange:ElementRange = 
                ElementRange.createElementRange(textFlow, anchorPosition, activePosition); 
            
            return selRange.getCommonCharacterFormat();
        }
    }
    
    /**
     *  @private
     *  To get the format of the container without using a SelectionManager.
     *  The method should be kept in sync with the version in the 
     *  SelectionManager.
     */
    mx_internal function getCommonContainerFormat():ITextLayoutFormat
    {
        var textFlow:TextFlow = getTextFlowWithComposer();
        
        // absoluteStart and absoluteEnd values not used. 
        var selRange:ElementRange = 
            ElementRange.createElementRange(textFlow, 0, textFlow.textLength - 1); 
        
        return selRange.getCommonContainerFormat();
    }
    
    /**
     *  @private
     *  To get the format of a paragraph without using a SelectionManager.
     *  The method should be kept in sync with the version in the 
     *  SelectionManager.
     */
    mx_internal function getCommonParagraphFormat(
                                        anchorPosition:int, 
                                        activePosition:int):ITextLayoutFormat
    {
        if (anchorPosition == -1 || activePosition == -1)
            return null;
                
        var textFlow:TextFlow = getTextFlowWithComposer();
    
        // ElementRange will order the selection points.
        var selRange:ElementRange = 
            ElementRange.createElementRange(textFlow, anchorPosition, activePosition); 
                
        return selRange.getCommonParagraphFormat();
    }
    
    /**
     *  @private
     *  Insert or append text to the textFlow without using an EditManager.
     *  If there is a SelectionManager or EditManager its selection will be
     *  updated at the end of the operation to keep it in sync.
     */
    mx_internal function insertTextOperation(insertText:String, 
                                             anchorPosition:int, 
                                             activePosition:int):Boolean
    {
        // No insertion point.
        if (anchorPosition == -1 || activePosition == -1)
            return false;
        
        var textFlow:TextFlow = getTextFlowWithComposer();
        
        var absoluteStart:int = getAbsoluteStart(anchorPosition, activePosition);
        var absoluteEnd:int = getAbsoluteEnd(anchorPosition, activePosition);
        
        // Need to get the format of the insertion point so that the inserted
        // text will have this format.
        var pointFormat:ITextLayoutFormat = 
            getCommonCharacterFormat(absoluteStart, absoluteStart);

        var operationState:SelectionState = 
            new SelectionState(textFlow, absoluteStart, absoluteEnd, pointFormat);
 
        // If there is an interaction manager, this keeps it in sync with
        // the results of this operation.
        operationState.selectionManagerOperationState = true;
        
        var op:InsertTextOperation = 
            new InsertTextOperation(operationState, insertText);
        
        // Generations don't seem to be used in this code path since we
        // aren't doing composite, merge or undo operations so they were
        // optimized out.
        
        var success:Boolean = op.doOperation();
        if (success)
        {
            textFlow.normalize(); 
            
            textFlow.flowComposer.updateAllControllers(); 

            var insertPt:int = absoluteEnd - (absoluteEnd - absoluteStart) +
                                    + insertText.length;            
            
            // No point format.
            var selectionState:SelectionState =
                new SelectionState(textFlow, insertPt, insertPt);
            
            var selectionEvent:SelectionEvent = 
                new SelectionEvent(SelectionEvent.SELECTION_CHANGE, 
                                   false, false, selectionState);

            textFlow.dispatchEvent(selectionEvent);
            
            scrollToRange(insertPt, insertPt);            
        } 

        return success;
    }

    /**
     *  Note:  It is probably a TLF bug that, if delayedUpdates is true, we have to call 
     *  updateAllControllers before doing a format operation to guarantee the correct
     *  results.
     */
    mx_internal function getTextFlowWithComposer():TextFlow
    {
        var textFlow:TextFlow = getTextFlow();
        
        // Make sure there is a text flow with a flow composer.  There will
        // not be an interaction manager if editingMode is read-only.  If
        // there is an interaction manager flush any pending inserts into the
        // text flow unless we are delaying updates in which case we may have to finish
        // composition.
        if (composeState != TextContainerManager.COMPOSE_COMPOSER)
        {
            convertToTextFlowWithComposer();
        }
        else if (textFlow.interactionManager)
        {
            const editManager:IEditManager = textFlow.interactionManager as IEditManager;
            if (editManager && editManager.delayUpdates)
                editManager.updateAllControllers();
            else
                textFlow.interactionManager.flushPendingOperations();
        }
        
        return textFlow;
    }
        
    /**
     *  @private
     */
    private function getAbsoluteStart(anchorPosition:int, activePosition:int):int
    {
        return (anchorPosition < activePosition) ? 
                    anchorPosition : activePosition;
    }
    
    /**
     *  @private
     */
    private function getAbsoluteEnd(anchorPosition:int, activePosition:int):int
    {
        return (anchorPosition > activePosition) ? 
                    anchorPosition : activePosition;
    }
    
    //--------------------------------------------------------------------------
    //
    //  Overridden event handlers
    //
    //--------------------------------------------------------------------------
        
    /**
     *  @private
     */
    override public function focusInHandler(event:FocusEvent):void
    {
        textDisplay.focusInHandler(event);

        super.focusInHandler(event);
    }    

    /**
     *  @private
     */
    override public function focusOutHandler(event:FocusEvent):void
    {
        textDisplay.focusOutHandler(event);

        super.focusOutHandler(event);
    }    

    /**
     *  @private
     */
    override public function keyDownHandler(event:KeyboardEvent):void
    {
        textDisplay.keyDownHandler(event);

        if (!event.isDefaultPrevented())
        {
            var clone:KeyboardEvent = KeyboardEvent(event.clone());
            super.keyDownHandler(clone);
            if (clone.isDefaultPrevented())
                event.preventDefault();
        }
    }

    /**
     *  @private
     */
    override public function keyUpHandler(event:KeyboardEvent):void
    {
        if (!event.isDefaultPrevented())
        {
            var clone:KeyboardEvent = KeyboardEvent(event.clone());
            super.keyUpHandler(clone);
            if (clone.isDefaultPrevented())
                event.preventDefault();
        }
    }
        
    /**
     *  @private
     */
    override public function mouseDownHandler(event:MouseEvent):void
    {
        textDisplay.mouseDownHandler(event);
        
        super.mouseDownHandler(event);
    }
        
    /**
     *  @private
     *  This handler gets called for ACTIVATE events from the player
     *  and FLEX_WINDOW_ACTIVATE events from Flex.  Because of the
     *  way AIR handles activation of AIR Windows, and because Flex
     *  has its own concept of popups or pseudo-windows, we
     *  ignore ACTIVATE and respond to FLEX_WINDOW_ACTIVATE instead
     */
    override public function activateHandler(event:Event):void
    {
        // block ACTIVATE events
        if (event.type == Event.ACTIVATE)
            return;

        super.activateHandler(event);

        // TLF ties activation and focus together.  If a Flex PopUp is created 
        // it is possible to get deactivate/activate events without any 
        // focus events.  If we have focus when we are activated, the selection 
        // state should be SelectionFormatState.FOCUSED not 
        // SelectionFormatState.UNFOCUSED since there might not be a follow on
        // focusIn event.
        if (editingMode != EditingMode.READ_ONLY &&
            textDisplay.getFocus() == textDisplay)
        {
            var im:SelectionManager = SelectionManager(beginInteraction());
            im.setFocus();
            endInteraction();
       }
    }

    /**
     *  @private
     *  This handler gets called for DEACTIVATE events from the player
     *  and FLEX_WINDOW_DEACTIVATE events from Flex.  Because of the
     *  way AIR handles activation of AIR Windows, and because Flex
     *  has its own concept of popups or pseudo-windows, we
     *  ignore DEACTIVATE and respond to FLEX_WINDOW_DEACTIVATE instead
     */
    override public function deactivateHandler(event:Event):void
    {
        // block DEACTIVATE events
        if (event.type == Event.DEACTIVATE)
            return;

        super.deactivateHandler(event);
    }

    /**
     *  @private
     *  sandbox support
     */
    override public function beginMouseCapture():void
    {
        super.beginMouseCapture();
        textDisplay.systemManager.getSandboxRoot().addEventListener(SandboxMouseEvent.MOUSE_UP_SOMEWHERE, mouseUpSomewhereHandler);
        textDisplay.systemManager.getSandboxRoot().addEventListener(SandboxMouseEvent.MOUSE_MOVE_SOMEWHERE, mouseMoveSomewhereHandler);
    }

    /**
     *  @private
     *  sandbox support
     */
    override public function endMouseCapture():void
    {
        super.endMouseCapture();
        textDisplay.systemManager.getSandboxRoot().removeEventListener(SandboxMouseEvent.MOUSE_UP_SOMEWHERE, mouseUpSomewhereHandler);
        textDisplay.systemManager.getSandboxRoot().removeEventListener(SandboxMouseEvent.MOUSE_MOVE_SOMEWHERE, mouseMoveSomewhereHandler);
    }

    //--------------------------------------------------------------------------
    //
    //  Event handlers
    //
    //--------------------------------------------------------------------------
    
    private function mouseUpSomewhereHandler(event:Event):void
    {
        mouseUpSomewhere(event);
    }

    private function mouseMoveSomewhereHandler(event:Event):void
    {
        mouseMoveSomewhere(event);
    }
}

}
