////////////////////////////////////////////////////////////////////////////////
//
//  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 com.adobe.linguistics.spelling
{
	import com.adobe.linguistics.spelling.framework.SpellingConfiguration;
	import com.adobe.linguistics.spelling.framework.SpellingService;
	import com.adobe.linguistics.spelling.framework.ui.HaloHighlighter;
	import com.adobe.linguistics.spelling.framework.ui.HaloWordProcessor;
	import com.adobe.linguistics.spelling.framework.ui.IHighlighter;
	import com.adobe.linguistics.spelling.framework.ui.IWordProcessor;
	import com.adobe.linguistics.utils.TextTokenizer;
	import com.adobe.linguistics.utils.Token;

	import flash.events.Event;
	import flash.events.FocusEvent;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import flash.net.SharedObject;
	import flash.net.URLLoader;
	import flash.net.URLRequest;
	import flash.text.TextField;
	import flash.utils.Dictionary;

	import mx.controls.RichTextEditor;
	import mx.controls.TextArea;
	import mx.controls.TextInput;
	import mx.core.UIComponent;
	import mx.core.mx_internal;
	import mx.events.ScrollEvent;

	use namespace mx_internal;
	
	/**
	 * <p>A comprehensive convenience class that bundles a context menu UI, 
	 * the spelling engine, the dictionary loader, and user dictionary support 
	 * to enable a single-line integration of spell checking functionality into 
	 * any text related Flex UI component.  While this class drastically simplifies 
	 * the effort to enable spell checking functionality in a Flex UI component, 
	 * it does shield the developer form controlling detailed behaviors of the spell 
	 * checker and the user dictionary storage options. </p>
	 *
	 * <p>This class provides a simple UI for some standard Flex UI components.
	 *	It is not intended to address a complete user interface.
	 *	Instead, it presents a basic user interface for some commonly used Flex UI components.</p>
	 *
	 * <p>For advanced text editing applications, more complex features are likely required.
	 *	For those applications, we recommend bypassing this class and utilizing the <code>SpellChecker</code> class directly.</p>
	 *
	 * <p><code>SpellUI</code> uses the SpellingConfig.xml file to lookup corresponding resource files for a given locale.
	 * The default location of SpellingConfig.xml is [yourapplicationDirectory]/SpellingConfig.xml. This could be customized using 
	 * <code>spellingConfigUrl</code> property of <code>SpellUI</code>. You don't have to change the content of this file. However,
	 * if you want to add a new language, to use an alternative dictionary or to customize the location for your dictionaries, you can modify it. 
	 * There's an known issue with IIS web server when loading dictionary files with unknown extensions, in which case you can modify the XML to work around it.</p><p>
	 * A sample SpellingConfig.xml will look as follows:
	 * <listing version="3.0">
	 * <pre class="preWrapper">
 	 * &lt;?xml version=&quot;1.0&quot; encoding='UTF-8'?&gt;
 	 * &lt;SpellingConfig&gt;
 	 *   	&lt;LanguageResource language=&quot;English&quot; 	  languageCode=&quot;en_US&quot; ruleFile=&quot;dictionaries/en_US/en_US.aff&quot; dictionaryFile=&quot;dictionaries/en_US/en_US.dic&quot;/&gt;
	 *    	&lt;LanguageResource language=&quot;Spanish&quot;    languageCode=&quot;es_ES&quot; ruleFile=&quot;dictionaries/es_ES/es_ES.aff&quot; dictionaryFile=&quot;dictionaries/es_ES/es_ES.dic&quot;/&gt;
 	 *   	&lt;LanguageResource language=&quot;Portuguese&quot; languageCode=&quot;pt_PT&quot; ruleFile=&quot;dictionaries/pt_PT/pt_PT.aff&quot; dictionaryFile=&quot;dictionaries/pt_PT/pt_PT.dic&quot;/&gt;
 	 *  	 &lt;LanguageResource language=&quot;Italian&quot; 	  languageCode=&quot;it_IT&quot; ruleFile=&quot;dictionaries/it_IT/it_IT.aff&quot; dictionaryFile=&quot;dictionaries/it_IT/it_IT.dic&quot;/&gt;
 	 * &lt;/SpellingConfig&gt;</pre>
	 *
	 * </listing>
	 * Note: The languageCode can be an arbitrary value, as long as you are consistent when passing them to the Squiggly classes. 
	 * However, we highly encourage you to follow the two part Unicode language identifier format. 
	 * For more information, please consult the latest Unicode Technical Standard that can be found at: http://unicode.org/reports/tr35/.</p>
	 * 
	 * @playerversion Flash 10
	 * @langversion 3.0
	 */
	public class SpellUI
	{
		private var hh:IHighlighter;
		private var hw:IWordProcessor;
				
		
		private var _checkLastWord:Boolean = true;
		
		private var _spellingEnabled:Boolean;
		
		private var _actualParent:*;
		private var isHaloComponent:Boolean;

		//New Added below
		private var mTextField:TextField;
				
		private var _dictname:String = new String();	
		
		private var _userdict:UserDictionary = null;
		private var _sharedobj:SharedObject = null;
		private var scm:SpellingContextMenu;	
		private var _newchecker:SpellChecker = null;
		private var _resource_locale:Object = null;
		private var _spellingservice:SpellingService = null;
		
		private static var _contextMenuEntries:Object = {enable:"Enable Spelling", disable:"Disable Spelling", add:"Add to dictionary"};
		private static var _spellingConfigUrl:String = "SpellingConfig.xml";
		
		private static var _UITable:Dictionary= new Dictionary();
		private static var _parentTable:Dictionary= new Dictionary();
		private static var _cacheDictTable:Dictionary= new Dictionary();
		
		private static var _configXML:XML = null;
		private static var _configXMLLoading:Boolean = false;
		private static var _configXMLLoader:URLLoader = new URLLoader();
		
		
		
		// Work around for the memory usage problem, ideally a better fix is to provide a dicitonary unload function
		private static var _cache:Object = {};

		/**
		 * Enable the spell checking feature in the specified language for a UI component. Once a component is spell checking enabled, misspelled words will be highlighted with a squiggly line. Users can 
		 * right click on a misspelled word to see the suggestions in the context menu.
		 * 
		 *
		 *
		 * @param comp	A text editing Flex UI component. It can be a mx <code>TextArea</code>, <code>TextInput</code> or <code>RichTextEditor</code>. 
		 * If you are using AdobeSpellingUIEx.swc, it can also be a spark <code>TextArea</code> or <code>TextInput</code>.
		 * @param lang	The language code used for spell checking, for example <code>en_US</code>. it will lookup the SpellingConfig.xml file to access corresponding resource files.
		 * SpellingConfig.xml should be located at the same folder as your main mxml source file. You don't have to change the content of this file. However,
		 * if you want to add a new language, to use an alternative dictionary or to customize the location for your dictionaries, you can modify it. There's an known issue with
		 * IIS web server when loading dictionary files with unknown extensions, in which case you can modify the XML to work around it.
		 * 
		 * 
		 *
		 * @includeExample Examples/Flex/SquigglyUIExample/src/SquigglyUIExample.mxml
		 * @playerversion Flash 10
		 * @langversion 3.0
		 */
		public static function enableSpelling(comp:UIComponent, lang:String):void
		{
			if ( lang == null ) return;
		 	// TODO: Change dict parameter type to a SpellCheck class or a URL string.
			var txt:* = getComponentTextModel(comp);
			
			if ( txt==null || _UITable[comp]!=undefined )
				return;
			
			// TODO: dangerous, is garbage collection going to clear this?
			_UITable[comp]=new SpellUI(txt, lang);
			_parentTable[txt] = comp;
			_cacheDictTable[comp]=lang;
		}
		
		/**
		 * Set the spelling context menu entries. This uses the flex object as an associative array for extensibility. 
		 * <code>entries</code> should have all the customized contextMenu entries including <code>enable (spelling), 
		 * disable (spelling) and add (to dictionary)</code>. To ensure a consistent contextMenu within your application, 
		 * the spelling context menu entries you provide here are applied to all UI components. We recommend you use this API
		 * with Flex resource for localization. Make sure to also have a look at the Flex localization documentation.
		 * 
		 * @see http://livedocs.adobe.com/flex/3/html/help.html?content=l10n_1.html 
		 * 
		 * @param entries A flex Ojbect that looks like <code>entries:Object = {enable:"Enable Spelling", disable:"Disable Spelling", 
		 * add:"Add to dictionary"}</code>. If you don't customize the contextMenu, the default contextMenu in English will be used.
		 * We recommend that you use the Flex localization resource to obtain these strings. 
		 * @return <code>True</code> if the spelling menu is successfully customized, <code>false</code> if it fails. Possible failure 
		 * reasons include passing the wrong object or missing some required entries. If the function fails, the contextMenu is left unchanged.
		 * 
		 * 
		 * @includeExample Examples/Flex/CustomContextMenu/src/CustomContextMenu.mxml
		 * @includeExample Examples/Flex/ContextMenuWithResource/src/ContextMenuWithResource.mxml
		 * @playerversion Flash 10
		 * @langversion 3.0
		 */
		public static function setSpellingMenuEntries(entries:Object):Boolean
		{
			if (entries.enable && entries.disable && entries.add && (entries.enable != "") && (entries.disable != "") && (entries.add != ""))
			{
					_contextMenuEntries = entries;
					return true;
			}
			else
				return false;
		}

		/**
		 * Get the spelling context menu entries. 
		 * 
		 * @return A flex <code>Object</code> containing the spelling context menu entries. If you haven't customized the entries, you get the default associative array <code>{enable:"Enable Spelling", disable:"Disable Spelling", add:"Add to dictionary"}</code>
		 * @playerversion Flash 10
		 * @langversion 3.0
		 */		
		public static function getSpellingMenuEntries():Object
		{
			return _contextMenuEntries;
		}
			
		/**
		 * The URL for the spelling config xml file. If you haven't specified it, the default URL is [applicationDirectory]/SpellingConfig.xml. Note that we don't validate the URL, if the file doesn't exist, you will get an error when calling enableSpelling() function.
		 *
		 * @example The following code customize the spellingConfigUrl before enabling spell checking.
		 * <listing version="3.0">
		 * SpellUI.spellingConfigUrl = "./config/MySpellingConfig.xml";
		 * SpellUI.enableSpelling(textArea, "es_ES");
		 * </listing>
		 */
		public static function get spellingConfigURL():String
		{
			return _spellingConfigUrl;
		}
		
		public static function set spellingConfigURL(url:String):void
		{
			if (url == null) throw new Error("URL can't be null");
			_spellingConfigUrl = url;
		}
		

			
		/**
		 * Disable the spell checking feature for a UI component.
		 * 
		 * @param comp	A text editing Flex UI component.
		 * @playerversion Flash 10
		 * @langversion 3.0
		 */
		public static function disableSpelling(comp:UIComponent):void{
			if ( _UITable[comp] == undefined )
				return;
			var _ui:SpellUI = _UITable[comp];
			if ( _ui != null) _ui.cleanUp();
			var dictName:String = _cacheDictTable[comp];
			var cleanUPDictionaryCount:int = 0;
			for each ( var _dictName:String in _cacheDictTable ) {
				if ( _dictName == dictName  )
					cleanUPDictionaryCount++;
			}
			if ( cleanUPDictionaryCount == 1 ) {
				_cache[dictName] = undefined;
			}
			delete _UITable[comp];
			delete _cacheDictTable[comp];
			
		}
		
		/**
		 @private
		 (This property is for Squiggly Developer use only.)
		 */
		public static function get UITable():Dictionary {
			return _UITable;
		}
		
		/**
		 @private
		 (This property is for Squiggly Developer use only.)
		 */
		public function set spellingEnabled(value:Boolean):void {
			_spellingEnabled = value;
		}
		
		/**
		 @private
		 (This property is for Squiggly Developer use only.)
		 */
		public static function get parentComp():Dictionary {
			return _parentTable;
		}
		
		private static function getComponentTextModel(comp:UIComponent):* {
			var txt:TextField = null;
			if ( (comp == null) || !( (comp is TextArea) || (comp is TextInput) || (comp is RichTextEditor) ) )
				return null;
			if ((comp as RichTextEditor) != null) {
				txt = (comp as RichTextEditor).textArea.getTextField() as TextField;
			}
			else if ((comp as TextArea) != null){
				txt = (comp as TextArea).getTextField() as TextField;
			}
			else if ((comp as TextInput) != null) {
				txt = (comp as TextInput).getTextField() as TextField;
			}
			else {
				// do nothing if it's not a valid text component
				return null;
			}
			return txt;
		}
		
		/**
		 * Constructs a SpellUI object.
		 *	@private
		 *
		 *	@param	textModel	A Flex UI component to include spell-check capability.
		 *	@param	lang		The language code to use for spell checking.
		 *
		 * @playerversion Flash 10
		 * @langversion 3.0
		 */			
		public function SpellUI(textModel:*, lang:String)
		{		
			// TODO: Consider making this method invisible to user, only expose the static function.
			if ( textModel is TextField ) {
				isHaloComponent=true;
			}else {
				// do nothing, we only accept textField and TextFlow here....
				return;
			}
			_actualParent = textModel;
			
			//New Added below -- check if text field needs to be extracted from textModel
			mTextField = textModel;
						
			mTextField.addEventListener(FocusEvent.FOCUS_OUT, handleFocusOut);
			mTextField.addEventListener(ScrollEvent.SCROLL, spellCheckScreen);
			mTextField.parent.addEventListener(Event.RENDER, spellCheckScreen);
			mTextField.parent.addEventListener(Event.CHANGE, handleChangeEvent);
			_dictname = lang;			
			loadConfig();
			
		}
		
		private function spellCheckScreen(event:Event):void
		{
			doSpellingJob();
		}
		
		private function handleFocusOut(event:FocusEvent):void
		{
			_checkLastWord = true;
			doSpellingJob();
		}
		
		private function handleChangeEvent( event:Event ) :void {
			_checkLastWord = false;
			doSpellingJob();
		}
				
		/*private function doSpelling():void
		{
			_checkLastWord = true;
			doSpellingJob();
		}*/
		
		/**
		 @private
		 (This property is for Squiggly Developer use only.)
		 */		
		public function doSpellingJob():void
		{
			if (_spellingEnabled == false) return;
			spellCheckRange(getValidFirstWordIndex(), getValidLastWordIndex());
		}
		
		private function spellCheckRange(start:uint, end:uint):void {
			//hh.preSpellCheckRange(start, end);
			hh.clearSquiggles();
			
			//if (end <= start) return;
			var firstLine:int = mTextField.getLineIndexOfChar(start);
			var rect:Rectangle = mTextField.getCharBoundaries(start);
			var counter:uint = start;
			var numLines:Number = 0;
			
			/* mTextField.getCharBoundaries returns null for blank lines and for end of line characters. Placing this workaround
			to count line heights until a non-null bounding rectangle is found */
			
			while (rect == null) {
				if (counter+1 > end) {
						rect = new Rectangle(0,0,0,0);
						break;
					}				
				if(mTextField.text.charCodeAt(counter)<0x0300 || mTextField.text.charCodeAt(counter)>0x036F)//not in diacritic combining range
				{
					numLines += mTextField.getLineMetrics(firstLine).height;
					firstLine++;
				}
				counter++;
				rect = mTextField.getCharBoundaries(counter);
			}
			
			var yoffset:Number = rect.y - numLines;	
			var pleft:uint = (mTextField.parent as UIComponent).getStyle("paddingLeft");
			var ptop:uint = (mTextField.parent as UIComponent).getStyle("paddingTop");
			
			var offsetPoint:Point = new Point(pleft, ptop-yoffset); 
						
			var tokenizer:TextTokenizer = new TextTokenizer(mTextField.text.substring(start,end));
			//var seps:Vector.<int> = new Vector.<int>();
			//seps.push(new int(34));
			//tokenizer.ignoredSeperators = seps;
			var tokens:Vector.<Token> = new Vector.<Token>();
			
			hh.offsetPoint = offsetPoint;
			
			for ( var token:Token = tokenizer.getFirstToken(); token != tokenizer.getLastToken(); token= tokenizer.getNextToken(token) ) {
				var result:Boolean=_spellingservice.checkWord(mTextField.text.substring(token.first+start, token.last+start));					
				if (!result){
					if (_checkLastWord || (token.last+start != mTextField.text.length)) 
						//hh.highlightWord(token.first+start, token.last+start-1);
						//tokens.push(new Token(token.first+start, token.last+start-1));
						hh.drawSquiggleAt(new Token(token.first+start, token.last+start-1));
				}
				
			}
			//hh.postSpellCheckRange(start, end);
			//hh.offsetPoint = offsetPoint;
			//hh.drawSquiggles(tokens);
		}
		
		
		private function getValidFirstWordIndex():int{
			return mTextField.getLineOffset(mTextField.scrollV-1);
		}
		
		private function getValidLastWordIndex():int{
			return mTextField.getLineOffset(mTextField.bottomScrollV-1)+mTextField.getLineLength(mTextField.bottomScrollV-1);
		}

		private function loadConfig():void{
			_resource_locale = SpellingConfiguration.resourceTable.getResource(_dictname);
			
			if ((_resource_locale != null) || (SpellUI._configXML != null)) 
				loadConfigComplete(null);
			else {	
				SpellUI._configXMLLoader.addEventListener(Event.COMPLETE, loadConfigComplete);
			
				if (SpellUI._configXMLLoading == false)
				{
					SpellUI._configXMLLoader.load(new URLRequest(_spellingConfigUrl));
					SpellUI._configXMLLoading = true;
				}
			}
		}
		
		private function loadConfigComplete(evt:Event):void{
			if (_resource_locale == null) {
				if (SpellUI._configXML == null)
					SpellUI._configXML= new XML(evt.target.data);
			
				SpellingConfiguration.resourceTable.setResource(_dictname,{rule:SpellUI._configXML.LanguageResource.(@languageCode==_dictname).@ruleFile, 
																		dict:SpellUI._configXML.LanguageResource.(@languageCode==_dictname).@dictionaryFile});
			}
			//New Added
			_spellingservice = new SpellingService(_dictname);
			_spellingservice.addEventListener(Event.COMPLETE, loadDictComplete);
			_spellingservice.init();
		}
		

		
		
		private function loadDictComplete(evt:Event):void
		{					
			
			
			// Lazy loading the UD only when the main dict is loaded successfully
			if ((SpellUI._cache["Squiggly_UD"] as UserDictionary) == null)
			{
				_sharedobj = SharedObject.getLocal("Squiggly_v03");
				var vec:Vector.<String> = new Vector.<String>();
				if (_sharedobj.data.ud) {
					for each (var w:String in _sharedobj.data.ud)
						vec.push(w);
				}
				_userdict = new UserDictionary(vec);
				
				SpellUI._cache["Squiggly_SO"] = _sharedobj;
				SpellUI._cache["Squiggly_UD"] = _userdict;
			}
			else 
			{
				_sharedobj = SpellUI._cache["Squiggly_SO"];
				_userdict = SpellUI._cache["Squiggly_UD"];
			}
			_spellingservice.addUserDictionary(_userdict);
			//Adding default behaviour to accomodate ignoring of abbreviations bug#2756840
			_spellingservice.ignoreWordWithAllUpperCase=true;
			
			
			// Add the context menu, this might be not successful
			scm = null;
			try {
				addContextMenu(null);
			}
			catch (err:Error)
			{
				// TODO: error handling here
			}
			_actualParent.addEventListener(Event.ADDED_TO_STAGE, addContextMenu);
		}
		

		private function addContextMenu(event:Event):void
		{
			if ( scm != null ) return;
			if ( isHaloComponent ) {
				hh= new HaloHighlighter( _actualParent);
				hw= new HaloWordProcessor( _actualParent);
			}else {
				trace("error now, later will be true");
			}
		
			scm =  new SpellingContextMenu(hh, hw, _spellingservice, _actualParent, _actualParent.contextMenu); 
			scm.setIgnoreWordCallback( addWordToUserDictionary );
			
			// Halo need this
			if (_actualParent.contextMenu == null)
			{
				_actualParent.contextMenu = scm.contextMenu;
			}
			
			//hh.spellingEnabled=true;
			_spellingEnabled = true;
			try {
				doSpellingJob();
			}
			catch (err:Error)
			{
				// If it fails here, it should later triggered by the render event, so no need to do anything
			}
			
			
		}
		
		private function addWordToUserDictionary(word:String):void
		{
			_userdict.addWord(word);
			
			// TODO: serialization here might affect ther performance
			_sharedobj.data.ud = _userdict.wordList;
			
		}
		/**
		 *	@private
		 */
		private function cleanUp():void {
			if(hh != null)
			{
				hh.clearSquiggles();
			}

			if(scm)
			{
				scm.cleanUp();
			}

			_actualParent.removeEventListener(Event.ADDED_TO_STAGE, addContextMenu);
			
			mTextField.removeEventListener(ScrollEvent.SCROLL, spellCheckScreen);
			mTextField.parent.removeEventListener(Event.RENDER, spellCheckScreen);
			mTextField.parent.removeEventListener(Event.CHANGE, handleChangeEvent);
			mTextField.removeEventListener(FocusEvent.FOCUS_OUT, handleFocusOut);	
		}
		
	}
}
