////////////////////////////////////////////////////////////////////////////////
//
//  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 flashx.textLayout.accessibility
{
	import flash.accessibility.Accessibility;
	import flash.accessibility.AccessibilityImplementation;
	import flash.accessibility.AccessibilityProperties;
	import flash.display.DisplayObject;
	import flash.events.Event;
	
	import flashx.textLayout.edit.EditingMode;
	import flashx.textLayout.edit.ISelectionManager;
	import flashx.textLayout.elements.FlowElement;
	import flashx.textLayout.elements.FlowLeafElement;
	import flashx.textLayout.elements.GlobalSettings;
	import flashx.textLayout.elements.ParagraphElement;
	import flashx.textLayout.elements.TextFlow;
	import flashx.textLayout.events.CompositionCompleteEvent;
	import flashx.textLayout.tlf_internal;
	
	use namespace tlf_internal;
    //TODO this is in text_edit... which violates MVC yet again... what to do?
    //import flashx.textLayout.events.SelectionEvent;
    
	//TODO handle selectable text when FP implements the new selection API:
	//     http://frpbugapp.macromedia.com/bugapp/detail.asp?id=217540
	//     To catch the selection changes reliably, listen for SelectionEvent,
	//     which is dispatched on the TextFlow whenever the selection changes.

    //TODO handle scrolling? might need to expose scrolling in here
    
	//TODO handle hyperlinks? I don't know if MSAA has a concept for this
	//    (what other text advanced features must be accessible? graphics?)
	//TODO what if there is HTML in it? strip it, or read it? we don't have an
	//     htmlText property, do we?

    // TODO Do we want to read the contents of each sprite and stop, even if the
    // text flows into other sprite, meaning we read text in taborder; or do we
    // want to read the entire model and not worry about the presentation
    // (simpler)? Not sure if I can get the contents of each sprite separately.
    
    // TODO TESTING:
    //   * Test that JAWS reads when setting the focus programmatically.
    //   * Tests for changing every part of the model programmatically -- role
    //     and state should update accordingly, visibility, and text contents.
    //   * Test that setting tabOrder reads as expected. What happens if you set
    //     tabOrder on multiple flowComposers?
    
    //TODO update this comment after integration
	/**
	 * @private
	 * The TextAccImpl class adds accessibility for text components.
	 * This hooks into DisplayObjects when TextFlow.container is set.
	 */
	public class TextAccImpl extends AccessibilityImplementation
	{
	    //TODO might want to put these constants in a new class if they are
	    //     used anywhere else.
	    
		/** Default state */
		protected static const STATE_SYSTEM_NORMAL:uint = 0x00000000;
		
		/** Read-only text */
		protected static const STATE_SYSTEM_READONLY:uint = 0x00000040;
		
		/** Inivisible text */
		//TODO unused, but supported state for text in MSAA
		protected static const STATE_SYSTEM_INVISIBLE:uint = 0x00008000;
		
		/** Default role -- read-only, unselectable text. */
		protected static const ROLE_SYSTEM_STATICTEXT:uint = 0x29;
		
		/** Editable OR read-only, selectable text. */
		protected static const ROLE_SYSTEM_TEXT:uint = 0x2a;
		
		/* When the name changes (name is the text conent in STATICTEXT). */
		protected static const EVENT_OBJECT_NAMECHANGE:uint = 0x800c;
		
		/* When the value changes (value is the text content in TEXT). */
		protected static const EVENT_OBJECT_VALUECHANGE:uint = 0x800e;
	
		/**
		 *  A reference to the DisplayObject that is hosting accessible text.
		 */
		//TODO for now this assumes only the first DO in a flow is accessible
		//     in the future each flow DO should host its own accimpl and read
		//     the text only for its own box.
		//
		//     Or... perhaps we use getChildIDArray to manage all the text
		//     flows if they are linked below some master component (but I don't
		//     think this is the way it will happen).
		protected var textContainer:DisplayObject;
		
		/**
		 *  A reference to the TextFlow where our text originates.
		 */
		protected var textFlow:TextFlow;
		
		/**
		 *  Constructor.
		 * 
		 *  @param textContainer The DisplayObject instance that this
		 *                       TextAccImpl instance is making accessible.
		 *  @param textFlow The TextFlow that is hosting the textContainer.
		 */
		public function TextAccImpl(textCont:DisplayObject, textFlow:TextFlow)
		{
			super();
	
			this.textContainer = textCont;
			this.textFlow = textFlow;
			
			// stub is true when you are NOT providing an acc implementation
			// reports to reader as graphic
			stub = false;
			
			if (textCont.accessibilityProperties == null)
			{
    			textCont.accessibilityProperties =
    			    new AccessibilityProperties();
			}

            //TODO
            // setup event listeners for text selection and model changes
            //textFlow.addEventListener(SelectionEvent.SELECTION_CHANGE,
            //                          eventHandler);
            textFlow.addEventListener(CompositionCompleteEvent.COMPOSITION_COMPLETE, eventHandler);
		}
		
		public function detachListeners():void
		{
			textFlow.removeEventListener(CompositionCompleteEvent.COMPOSITION_COMPLETE, eventHandler);
		}
		
		/**
		 *  Returns the system role for the text.
		 *
		 *  @param childID uint.
		 *  @return Role associated with the text.
		 */
		override public function get_accRole(childID:uint):uint
		{
		    // trace("get_accRole()");
		    
		    const iManager:ISelectionManager = textFlow.interactionManager;
		    if (iManager == null)
		    {
		        // non-selectable, non-editable text is STATICTEXT
		        return ROLE_SYSTEM_STATICTEXT
		    }
		    else // iManager is an IEditManager and/or ISelectionManager
		    {
		        // read-only selectable or editable selectable text are TEXT
		        return ROLE_SYSTEM_TEXT;
		    }
		}
		
		/**
		 *  Returns the state of the text.
		 *
		 *  @param childID uint.
		 *  @return Role associated with the text.
		 */
		override public function get_accState(childID:uint):uint
		{
		    // trace("get_accState()");
		    
		    const iManager:ISelectionManager = textFlow.interactionManager;
		    
		    //TODO handle STATE_SYSTEM_INVISIBLE for all cases below
		    //     and add an event to detect changes--does Flash support this?
		    
		    //TODO handle STATE_SYSTEM_PROTECTED for all cases below
		    //     if vellum gets a concept of password fields, then it needs to 
		    //     emit this value if the field is converted to a password;
		    //     otherwise the Flex framework will need to be sure to emit
		    //     this state in a text input component.
		    
		    // note: focus-related states are handled by the player
		    
		    if (iManager == null)
		    {
		        // non-selectable, non-editable text
		        return STATE_SYSTEM_READONLY;
		    }
		    // must check IEditManager before ISelectionManager (it can be both)
		    else if (iManager.editingMode == EditingMode.READ_WRITE)
		    {
		        // editable selectable text
		        return STATE_SYSTEM_NORMAL;
		    }
		    else // if (iManager instanceof ISelectionManager)
		    {
		        // read-only selectable text
		        return STATE_SYSTEM_READONLY;
		    }
		}
		
		/**
		 *  Returns the name of the text.
		 *
		 *  @param childID uint.
		 *  @return Name of the text.
		 */
		override public function get_accName(childID:uint):String
		{
		    // trace("get_accName()");
		    
		    switch (get_accRole(childID))
		    {
    		    case ROLE_SYSTEM_STATICTEXT:
    		    {
        		    //TODO this SHOULD come from TextConverter, but then there is a
        		    //     circular build dependency since importExport builds
        		    //     against model, and it probably violates mvc
        			//return TextConverter.export(textFlow,
        			//                         TextConverter.PLAIN_TEXT_FORMAT);
        			
        			//TODO this is probably expensive. is there a way to cache
        			//      this and know when dirty?
        			//TODO  look at the generation and determine when it's dirty
        			return exportToString(textFlow);
    		    }
    		    
		        case ROLE_SYSTEM_TEXT:
		        default:
            		return null;
    		}
		}
		
		/**
		 *  Returns the value of the text.
		 *
		 *  @param childID uint.
		 *  @return Name of the text.
		 */
		override public function get_accValue(childID:uint):String
		{
		    // trace("get_accValue()");
		    
		    switch (get_accRole(childID))
		    {
		        case ROLE_SYSTEM_TEXT:
    		    {
        		    //TODO this SHOULD come from TextConverter, but then there is a
        		    //     circular build dependency since importExport builds
        		    //     against model, and it probably violates mvc
        			//return TextConverter.export(textFlow,
        			//                         TextConverter.PLAIN_TEXT_FORMAT);
        			
        			// TODO this is probably expensive. is there a way to cache
        			//      this and know when dirty?
        			//TODO  look at the generation and determine when it's dirty
        			return exportToString(textFlow);
    		    }
    		    
    		    case ROLE_SYSTEM_STATICTEXT:
		        default:
            		return null;
    		}
		}

		/**
		 * Handles COMPOSITION_COMPLETE and SELECTION_CHANGE events,
		 * updates the MSAA model.
    	 */
    	protected function eventHandler(event:Event):void
    	{
    		switch (event.type)
    		{
                // This updates the entire accessibility DOM.
                // get_accName is probably expensive here, it happens ONLY if
                // JAWS is running, otherwise Accessibility.* calls are NOOP.
                //
                // Event does NOT fire when interactionManager changes; ideally
                // we'd want to tell MSAA the role changed, but apparently roles
                // are typically static and that's not a supported workflow.
                // instead, Flash occasionally polls the displaylist, e.g. when
                // you mouseover. calling updateProperties() doesn't necessarily
                // trigger role updates (calls to get_acc*()).
    			case CompositionCompleteEvent.COMPOSITION_COMPLETE:
    			{
    			    // TODO change childID from 0 if we use getChildIDArray
    			    //      otherwise delete this comment
	 				try {
	    				Accessibility.sendEvent(textContainer, 0,
    					                        EVENT_OBJECT_NAMECHANGE);
    					Accessibility.sendEvent(textContainer, 0,
    					                        EVENT_OBJECT_VALUECHANGE);
    					Accessibility.updateProperties();
					} catch (e_err:Error) {
	 					// generic error occurred.
                        // this can happen in the SA player since there is no
                        // Accessibility implementation.
	 				}
    				break;
    			}
    			
                //TODO when we have the FP selection APIs
    			// case SelectionEvent.SELECTION_CHANGE:
    			// {
                //   // this is just stubbed code, I don't know what *needs* to
                //   // be done for SELECTION_CHANGE
    			// 	Accessibility.sendEvent(textContainer, 0,
    			//                          EVENT_OBJECT_TEXTSELECTIONCHANGED);
    			// 	Accessibility.updateProperties();
    			// 	break;
    			// }
    		}
    	}
		
		/**
		 * TODO HACK, remove and refactor.
		 * 
		 * This is copied from PlainTextExportFilter, which I would prefer to
		 * access through TextConverter.export(textFlow,
		 *                                  TextConverter.PLAIN_TEXT_FORMAT);
		 * 
		 * But, PTEF is in importExport, which builds against text_model,
		 * which is a circular dependency.
		 * 
		 * Also, it seems to be adding a trailing newline, which is bad for
		 * accessibility unless it is really there.
		 * 
		 * Might want to export and strip out hyphens.
		 * Move it to the model?
		 */
		private static function exportToString(source:TextFlow):String
		{
			var leaf:FlowLeafElement = source.getFirstLeaf();
			var rslt:String = "";
			var curString:String = "";
			var discretionaryHyphen:String = String.fromCharCode(0x00AD);
			while (leaf)
			{
            	var p:ParagraphElement = leaf.getParagraph();
            	while (true)
            	{
            		curString = leaf.text;
            		
            		//split out discretionary hyphen and put string back together
					var temparray:Array = curString.split(discretionaryHyphen);
					curString = temparray.join("");
					
	               	rslt += curString;
					leaf = leaf.getNextLeaf(p);
					if (!leaf)
                    {
                        // we want newlines between paragraphs but not at the end
                    	rslt += "\n";
						break;
					}
            	}
            	leaf = p.getLastLeaf().getNextLeaf();
   			}
   			return rslt;
		}
		
		/** 
		 * The zero-based character index value of the first character in the current selection.
		 * Components which wish to support inline IME or Accessibility should call into this method.
		 *
		 * @return the index of the character at the anchor end of the selection, or <code>-1</code> if no text is selected.
		 * 
		 * @playerversion Flash 10.0
		 * @langversion 3.0
		 */
		public function get selectionActiveIndex():int
		{
			var selMgr:ISelectionManager = textFlow.interactionManager;
			var selIndex:int = -1;
			if(selMgr && selMgr.editingMode != EditingMode.READ_ONLY)
			{
				selIndex = selMgr.activePosition;
			}
			
			return selIndex;
		}
		
		/** 
		 * The zero-based character index value of the last character in the current selection.
		 * Components which wish to support inline IME or Accessibility should call into this method.
		 *
		 * @return the index of the character at the active end of the selection, or <code>-1</code> if no text is selected.
		 * 
		 * @playerversion Flash 10.0
		 * @langversion 3.0
		 */
		public function get selectionAnchorIndex():int
		{
			var selMgr:ISelectionManager = textFlow.interactionManager;
			var selIndex:int = -1;
			if(selMgr && selMgr.editingMode != EditingMode.READ_ONLY)
			{
				selIndex = selMgr.anchorPosition;
			}
			
			return selIndex;
		}
		
		/** Enable search index for Ichabod
		 * Returns the entire text of the TextFlow, or null if search index is not enabled
		 * @see GlobalSettings.searchIndexEnabled
		 */
		public function get searchText():String
		{
			return GlobalSettings.enableSearch ? textFlow.getText() : null;
		}
		
	}
}

