////////////////////////////////////////////////////////////////////////////////
//
//  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.core
{
	import com.adobe.linguistics.spelling.core.env.InternalConstants;
	import com.adobe.linguistics.spelling.core.rule.PrefixEntry;
	import com.adobe.linguistics.spelling.core.rule.SuffixEntry;
	import com.adobe.linguistics.spelling.core.utils.*;

	import flash.utils.Dictionary;
	import flash.utils.getTimer;

	public class SuggestionManager
	{
		
		private var _attributeMgr:LinguisticRule;
		private var _maxSug:int;
		private var _languageCode:String;
		private var _ckey:String;
		private var _cUpperTry:String;
		private var _cLowerTry:String;
		private var _cAllTry:String;
		private var _maxngramsugs:int;
		private var _fastMode:Boolean;
		
		private var _word:String;
		private var _guessSuggestions:SuggestionsResult;
		private var _guessWordList:SuggestionsResult;
		private var guess:Array = new Array (InternalConstants.MAX_GUESS);
		private var gscore:Array = new Array ( InternalConstants.MAX_GUESS);
		
		public function SuggestionManager( attrMgr:LinguisticRule, fastMode:Boolean = true )
		{
			this._maxSug = InternalConstants.MAXSUGGESTION;
			this._attributeMgr = attrMgr;
			this._ckey = this._attributeMgr.keyString;

			this._cAllTry  = this._attributeMgr.tryString;
			this._cUpperTry = "";
			this._cLowerTry = ""; // lower and netual...
			for ( var i:int = 0; (this._attributeMgr.tryString != null)&&(i < this._attributeMgr.tryString.length); ++i ) {
				if ( this._attributeMgr.tryString.charAt(i) == this._attributeMgr.tryString.charAt(i).toLocaleLowerCase() ) {
					this._cLowerTry+=this._attributeMgr.tryString.charAt(i);
				} else {
					this._cUpperTry+= this._attributeMgr.tryString.charAt(i);
				}
				
			}

			this._maxngramsugs = InternalConstants.MAXNGRAMSUGS;
			this._fastMode = fastMode;
			
			//initialized viriable for performance...
			_word=null;
			_guessSuggestions = new SuggestionsResult(InternalConstants.MAX_ROOTS, compareSuggestion );
			_guessWordList = new SuggestionsResult( InternalConstants.MAX_GUESS, compareSuggestion );
			if ( this._attributeMgr.maxNgramSuggestions > 0 ) this._maxngramsugs = this._attributeMgr.maxNgramSuggestions;
		}
		
		public function get fastMode():Boolean {
			return this._fastMode;
		}
		
		public function set fastMode( value:Boolean ) :void {
			this._fastMode = value;
		}
		
		private static function compareSuggestion( obj1:*, obj2:*):int {
			return (obj1.score-obj2.score);
		}
		
		
		public function set languageCode(value:String) :void {
			this._languageCode = value;	
		}
		
		public function get languageCode():String {
			return this._languageCode;
		}
		
		public function nsuggest( result:Array, word:String ):int {

			if ( !((result.length+this._maxngramsugs) <= this._maxSug) ) return result.length;


			var nsug:int = result.length;
			var i:int,j:int,sc:int, opt:int, n:int = word.length;
			var arr:Array;
			var sd:SquigglyDictionary;
			var dict:Dictionary;
			_word = word;
			var initCap:Boolean = (word.charAt(0) == word.charAt(0).toLocaleLowerCase() )? false:true;
			var wordCapValue:int = word.charAt(0).toLocaleUpperCase().charCodeAt(0);
			_guessSuggestions.clear();
			
			/* A filter based on string length, it could be */
			var rangeOffset:int =5;
			var endRange:int = word.length + (rangeOffset-2);
			var startRange:int =  (word.length>(rangeOffset+2)) ? (word.length-rangeOffset):2  ;
	
					var counter:Number=0
					var startTime:Number = getTimer();

			// exhaustively search through all root words
			// keeping track of the MAX_ROOTS most similar root words
			
			// word reversing wrapper for complex prefixes
			
			// set character based ngram suggestion for words with non-BMP Unicode characters
			
			//a filter for performance improvement...
			var firstCodeValue:Number =word.charCodeAt(0), lastCodeValue:Number = word.charCodeAt(word.length-1);
			
			
			for ( i=0;i<this._attributeMgr.dictionaryManager.dictonaryList.length; ++i ) {
				sd = this._attributeMgr.dictionaryManager.dictonaryList[i];
				dict = sd.dictionary;
				
				var lowerS:String;
				var he:HashEntry;
				opt = InternalConstants.NGRAM_LONGER_WORSE + InternalConstants.NGRAM_LOWERING;
				for( var key:String in dict ) {
					if ( (key.length < startRange) || (key.length > endRange) ) continue;
					if ( (this._fastMode) && (firstCodeValue != key.charCodeAt(0)) && (lastCodeValue != key.charCodeAt(key.length-1)) ) continue;
					counter++;

					sc = ngram( 3, _word,key,opt) + leftCommonSubString(_word, key, initCap, wordCapValue);
					
					if ( sc > 0  ) {
						if ( _guessSuggestions.size < InternalConstants.MAX_ROOTS ) {
							if ( dict[key].affixFlagVector && 
								(dict[key].testAffix( this._attributeMgr.forbiddenWord ) ||
								dict[key].testAffix( this._attributeMgr.onlyInCompound) ||
								dict[key].testAffix( this._attributeMgr.noSuggest ) ||
								dict[key].testAffix( InternalConstants.ONLYUPCASEFLAG )
								)) continue; 
							_guessSuggestions.insert( new SuggestionEntry(sc,key, dict[key] ) );
							if ( _guessSuggestions.size == InternalConstants.MAX_ROOTS ) {
								_guessSuggestions.buildheap();
							}
						}else {
							if ( sc > _guessSuggestions.front.score ) {
								_guessSuggestions.front.score = sc;
								_guessSuggestions.front.key =  key;
								_guessSuggestions.front.hashEntry = dict[key];
								_guessSuggestions.updateFront();
							}
						}
					}
				}
			}
			
			var thresh:int = 0;
			var mw:String;
			for ( var sp:int = 1; sp < 4; ++sp) {
				mw = word;
				for ( var k:int=sp; k<n; k+=4) {
					mw = mw.substring(0,k) + "*" + mw.substring(k+1);
				}
				thresh = thresh + ngram( n, word, mw, InternalConstants.NGRAM_ANY_MISMATCH + InternalConstants.NGRAM_LOWERING);
			}
			thresh = thresh /3;
			thresh --;

			// now expand affixes on each of these root words and
			// and use length adjusted ngram scores to select
			// possible suggestions
			_guessWordList.clear();


			//work arround for inconsitent ordered Dictionary table. bof
			if ( _guessSuggestions.isEmpty() ) return result.length;
			var lowestScore:int = _guessSuggestions.front.score;
			var indexArr:Array;
			if ( _guessSuggestions.size != _guessSuggestions.maxSize ){
				indexArr=_guessSuggestions.data.slice(0,_guessSuggestions.size).sortOn("key",Array.DESCENDING | Array.RETURNINDEXEDARRAY);
			}else{
				indexArr=_guessSuggestions.data.sortOn("key",Array.DESCENDING | Array.RETURNINDEXEDARRAY);
			}
			//work arround for inconsitent ordered Dictionary table. bof

			// root list;
			for each ( i in indexArr ) {
				//work arround for inconsitent ordered Dictionary table. bof
				if ( i==0 || _guessSuggestions.data[i].score == lowestScore ) continue;
				//work arround for inconsitent ordered Dictionary table. bof
				
				var candList:Array = new Array();
				var candOriginalList:Array = new Array();
				expandRootWord(candList,candOriginalList, InternalConstants.MAX_WORDS, _guessSuggestions.data[i].key, _guessSuggestions.data[i].hashEntry, word );
				for ( j=0; j < candList.length; ++j) {
					sc = ngram ( n, word, candList[j], InternalConstants.NGRAM_ANY_MISMATCH + InternalConstants.NGRAM_LOWERING) + leftCommonSubString(word, candList[j],initCap, wordCapValue);
					if ( (sc>thresh) ) {
						if ( _guessWordList.size < InternalConstants.MAX_GUESS ) {
							_guessWordList.insert( new GuessWord(sc,candList[j], null ) );
							if ( _guessWordList.size == InternalConstants.MAX_GUESS ) {
								_guessWordList.buildheap();
							}
						}else {
							if ( sc > _guessWordList.front.score ) {
								_guessWordList.front.score = sc;
								_guessWordList.front.key =  candList[j];
								_guessWordList.front.original = null;
								_guessWordList.updateFront();
							}
						}
						
					}
				}
			}

			// now we are done generating guesses
			// sort in order of decreasing score
			var guessArr:Array = _guessWordList.toArray().sortOn("score",Array.NUMERIC | Array.DESCENDING);


			// weight suggestions with a similarity index, based on
			// the longest common subsequent algorithm and resort
			var refobj:RefObject = new RefObject(0);
			var gl:String;
			for ( i=guessArr.length-1;i>= 0; --i ) {
				gl = guessArr[i].key.toLocaleLowerCase();
				var _lcs:int = StringUtils.lcslen(word, gl);
				// same characters with different casing
				if ( (n==gl.length) && (n == _lcs) ) {
					guessArr[i].score += 2000;
					break;
				}
				// heuristic weigthing of ngram scores
				guessArr[i].score += 
					// length of longest common subsequent minus length difference
					2 * _lcs - Math.abs((int) (n - guessArr[i].key.length)) +
					// weight length of the left common substring
					leftCommonSubString(word, gl,initCap, wordCapValue) +
					// weight equal character positions
					((_lcs == StringUtils.commonCharacterPositions(word, gl, refobj)) ? 1: 0) +
					// swap character (not neighboring)
					((refobj.ref) ? 1000 : 0);
			}

			guessArr = guessArr.sortOn("score", Array.NUMERIC | Array.DESCENDING);
			
			
			// copy over
			var oldnsug:int = nsug;
			var same:int = 0;
			for ( i=0;i< guessArr.length; ++i ) {
				if ( (nsug < this._maxSug) && (result.length < (oldnsug + this._maxngramsugs)) && (!same || (guessArr[i].score > 1000)) ) {
					var unique:int = 1;
					// leave only excellent suggestions, if exists
					if ( guessArr[i].score > 1000 ) same = 1;
					// don't suggest previous suggestions or a previous suggestion with prefixes or affixes
					for ( j=0;j< result.length; ++j) {
						if ( ( guessArr[i].key.indexOf(result[j]) != -1) || !checkWord(guessArr[i].key) ) unique = 0;
					}
					if ( unique ) {
						result.push( guessArr[i].key );
					}
				}
				
			}
			
					var endTime:Number = getTimer();
			return nsug;
		}
		
		private function testValidSuggestion(element:*, gw:GuessWord):Boolean {
			if ( gw.key.indexOf( element ) ) 
				return false;
			if ( !checkWord(element) ) return false; 
			return true;
		}

		private function expandRootWord(guessWordList:Array, guessOriginalList:Array, maxn:int, root:String, he:HashEntry, badWord:String) :void {
			// first add root word to list
			var nh:int = 0, i:int, j:int;
			var sfx:SuffixEntry;
			var pfx:PrefixEntry;
			var newWord:String;
			var crossFlagArray:Array = new Array();
			if ( (guessWordList.length < maxn) && 
			!( (he.affixFlagVector != null) &&
			( (this._attributeMgr.needAffix && he.testAffix(this._attributeMgr.needAffix)) || ( this._attributeMgr.onlyInCompound && he.testAffix(this._attributeMgr.onlyInCompound))))
			){
				guessWordList[nh] = root;
				guessOriginalList[nh] = root;
				crossFlagArray[nh] = false;
				nh++;
			}
			
			// handle suffixes
			for ( i=0; (he.affixFlagVector !=null) && (i<he.affixFlagVector.length);++i) {
				sfx= this._attributeMgr.suffixFlagTable[he.affixFlagVector.charAt(i)];
				while( sfx  ) {
					var index:int = badWord.lastIndexOf(sfx.affixKey);
					if ( (index != -1) && ( index== (badWord.length-sfx.affixKey.length)) ) {
						newWord = sfx.add(root);
						if ( newWord) {
							guessWordList[nh] = newWord;
							guessOriginalList[nh] = root;
							crossFlagArray[nh] = sfx.permissionToCombine;
							nh++;
						}
					}
					sfx = sfx.nextElementWithFlag; 
				}
			}
			
			// handle cross products of prefixes and suffixes
			var n:int = nh;
			for ( j=1;j<n;++j) {
				if( crossFlagArray[j] ) {
					for ( i=0;(he.affixFlagVector !=null) && (i<he.affixFlagVector.length);++i) {
						pfx = this._attributeMgr.prefixFlagTable[he.affixFlagVector.charAt(i)];
						while( pfx ) {
							if ( badWord.indexOf(pfx.affixKey)== 0 ) {
								newWord = pfx.add(guessWordList[j]);
								if ( newWord) {
									guessWordList[nh] = newWord;
									guessOriginalList[nh] = root;
									crossFlagArray[nh] = pfx.permissionToCombine;
									nh++;
								}
							}
							pfx = pfx.nextElementWithFlag;
						}
					}
				}
			}
			
			// now handle pure prefixes
			for ( i=0; (he.affixFlagVector !=null) && (i<he.affixFlagVector.length);++i) {
				pfx= this._attributeMgr.prefixFlagTable[he.affixFlagVector.charAt(i)];
				while( pfx  ) {
					if ( badWord.indexOf(pfx.affixKey) == 0 ) {
						newWord = pfx.add(root);
						if ( newWord) {
							guessWordList[nh] = newWord;
							guessOriginalList[nh] = root;
							crossFlagArray[nh] = pfx.permissionToCombine;
							nh++;
						}
					}
					pfx = pfx.nextElementWithFlag; 
				}
			}
				
		}
		
		/*
		 * ToDo: Since this is a generic algorithm, we might want move this code to StringUtils class.
		 */
		private function ngram(n:int, s1:String, s2:String, opt:int):int {

			var i:int,j:int,k:int,m:int,n:int;
	    	var nscore:int = 0, ns:int, l1:int, l2:int;

			l1 = s1.length;
			l2 = s2.length;
			if ( opt & InternalConstants.NGRAM_LOWERING ) s2=s2.toLowerCase();
			for ( i = 0; i<l1; i++ ) {
				if ( s2.indexOf( s1.charAt(i) ) != -1 ) ns++;
			}
			nscore = nscore + ns;
			if ( ns >= 2 ) {
				for (  j = 2; j<=n; j++ ) {
					ns = 0;
					for (  i = 0; i <=(l1-j); i++ ) {
	//					var tmp:String = s1.substr(i,i+j);
	//					tmp = s1.substring(i,i+j);
						if ( s2.indexOf( s1.substring(i,i+j) ) != -1 ) ns++;   // it could be signaficantly optimized If we can avoid to use substr() function....
					}
					nscore = nscore + ns;
					if (ns < 2) break;
				}
			}
			ns = 0;
			if (opt & InternalConstants.NGRAM_LONGER_WORSE) ns = (l2-l1)-2;
			if (opt & InternalConstants.NGRAM_ANY_MISMATCH) ns = Math.abs(l2-l1)-2;
			ns = (nscore - ((ns > 0) ? ns : 0));
			return ns;
			return 1;
		}

		
		/*
		 * Deprecated function for now...
		 * History: 
		 *          A pre-version of implementation for error correction. After I optimized the code for performance,
		 *          I drop this function by that time, but you know performance meassuring is a tricky problem... 
		 * ToDo: Need a revisit when we implementing complex-affix support and compound-word support.
		 */
		private function ngram1(n:int, s1:String, s2:String, opt:int):int {
	    	var nscore:int = 0, ns:int, l1:int, l2:int;
			
			var i:int,j:int,k:int,m:int,n:int;
			
			l1 = s1.length;
			l2 = s2.length;
			if ( opt & InternalConstants.NGRAM_LOWERING ) s2=s2.toLowerCase();
			for (  j = 1; j<=n; j++ ) {
				ns = 0;
				for (  i = 0; i <=(l1-j); i++ ) {
//					var tmp:String = s1.substr(i,i+j);
//					tmp = s1.substring(i,i+j);
					if ( s2.indexOf( s1.substring(i,i+j) ) != -1 ) ns++;   // it could be signaficantly optimized If we can avoid to use substr() function....
				}
				nscore = nscore + ns;
				if (ns < 2) break;
			}
			ns = 0;
			if (opt & InternalConstants.NGRAM_LONGER_WORSE) ns = (l2-l1)-2;
			if (opt & InternalConstants.NGRAM_ANY_MISMATCH) ns = Math.abs(l2-l1)-2;
			ns = (nscore - ((ns > 0) ? ns : 0));
			return ns;
			return 1;
		}
		
		/*
		 * ToDo: since this is a generic algorithm, we might want to move this function to StringUtils class.
		 */
		private function leftCommonSubString(s1:String,s2:String, initCap:Boolean, s1CapValue:int):int {
			var res:int = 1;
			if ( s1.charCodeAt(0) != s2.charCodeAt(0) && ( !initCap ) && (s1CapValue != s2.charCodeAt(0)) ) return 0;
			for( var i:int=1; (i< s1.length) && (s1.charCodeAt(i) == s2.charCodeAt(i)); ++i ) {
				res++;
			}
			return res;
		}
		
		
		public function suggest( result:Array, word:String, capType:int):int {
			var nsug:int = 0;

			// suggestions for an uppercase word (html -> HTML)
			if ( (nsug < this._maxSug) && (nsug > -1 ) ) {
				nsug = capchars(result,word,nsug);
			}
			
			// perhaps we made a typical fault of spelling
			if ( (nsug < this._maxSug) && (nsug > -1 ) ) {
				nsug = replchars( result, word, nsug );	
			}
			
			// perhaps we made chose the wrong char from a related set
			if ( (nsug < this._maxSug) && (nsug > -1 ) ) {
				nsug = mapchars( result, word, nsug );	
			}

			// did we swap the order of chars by mistake
			if ( (nsug < this._maxSug) && (nsug > -1 ) ) {
				nsug = swapchar( result, word, nsug );	
			}
			
			// did we swap the order of non adjacent chars by mistake
			if ( (nsug < this._maxSug) && (nsug > -1 ) ) {
				nsug = longswapchar( result, word, nsug );	
			}

			// did we just hit the wrong key in place of a good char (case and keyboard)
			if ( (nsug < this._maxSug) && (nsug > -1 ) ) {
				nsug = badcharkey( result, word, nsug );	
			}
			 // did we add a char that should not be there
			if ( (nsug < this._maxSug) && (nsug > -1 ) ) {
				nsug = extrachar( result, word, nsug );	
			}
			
			// did we forgot a char
			if ( (nsug < this._maxSug) && (nsug > -1 ) ) {
				nsug = forgotchar( result, word, nsug, capType );	
			}

			// did we move a char
			if ( (nsug < this._maxSug) && (nsug > -1 ) ) {
				nsug = movechar( result, word, nsug );	
			}

			// did we just hit the wrong key in place of a good char
			if ( (nsug < this._maxSug) && (nsug > -1 ) ) {
				nsug = badchar( result, word, nsug, capType );	
			}
			
			// did we double two characters
			if ( (nsug < this._maxSug) && (nsug > -1 ) ) {
				nsug = doubletwochars( result, word, nsug );	
			}
			
			// perhaps we forgot to hit space and two words ran together
			if ( (nsug < this._maxSug) && (nsug > -1 ) ) {
				nsug = twowords( result, word, nsug );	
			}

			return nsug;
		}
		
		
		
		private function mapchars( result:Array, word:String, nsug:int ) :int {
			if (word.length < 2) return nsug;
			if ( (nsug == this._maxSug) || (this._attributeMgr.mapFilterTable.length == 0) ) return nsug;
			var mapTable:Array = this._attributeMgr.mapFilterTable;
			var counter:int = 0;
			nsug = map_related(result, word, nsug, 0 ,mapTable, counter);
			
			return nsug;
		}		

		private function map_related( result:Array, word:String, nsug:int, startIndex:int, mapTable:Array, counter:int) :int {
			var totalCheckCount:int = 8; // for performance issue only... 8 means four level detection...
			var candidate:String;
			var in_map:int = 0;
			var j:int;
			counter++;
			if ( counter > totalCheckCount ) return nsug; // for performance issue only...
			if ( nsug == this._maxSug ) return nsug;
			if ( startIndex == word.length ) {
				var cwrd:int = 1;
				for (  j=0; j < result.length; ++j ) {
					if ( result[j]== word ) cwrd=0;
				}
				if ( cwrd && checkWord(word) ) {
					result.push(word);
					nsug++;
				}
				return nsug;
				
			}
			for ( var i:int = 0;i<mapTable.length ;++i ) {
				if ( mapTable[i].mapCharSet.indexOf(word.charAt(startIndex)) != -1 ) {
					in_map= 1;
					for ( j =0; j< mapTable[i].mapCharSet.length; ++j ) {
						candidate = word.substring(0,startIndex) +mapTable[i].mapCharSet.charAt(j)+word.substring(startIndex+1);
						nsug = map_related(result,candidate,nsug,(startIndex+1),mapTable, counter);
					}
				}				
			}
			
			if( !in_map) {
				nsug = map_related(result,word,nsug,(startIndex+1),mapTable, counter);
			}
			return nsug;
		} 
		
		private function twowords( result:Array, word:String, nsug:int ) :int {
			var candidate:String;
			var cwrd:int=1;
			var count:int=0;
			if (word.length < 3) return result.length;
			if ( result.length >= this._maxSug ) return result.length;
			
			for( var i:int=1;i<word.length;++i) {
				candidate = word.substring(0,i);
				if ( !checkWord(candidate) ) continue;
				candidate = word.substring(i);
				if ( checkWord(candidate) ) {
					candidate = word.substring(0,i) +" " + word.substring(i);
					for ( var j:int=0; j < result.length; ++j ) {
						if ( result[j]== candidate ) cwrd=0;
					}
					if ( cwrd ) {
						if ( result.length >= this._maxSug ) return result.length;
						result.push(candidate);
						nsug++;
					}
				}
			}

			return nsug;
		}		

		private function doubletwochars( result:Array, word:String, nsug:int ) :int {
			var candidate:String;
			var nstate:int=0;
			if (word.length < 5) return nsug;
			for (var i:int=2;i<word.length;++i) {
				if( word.charCodeAt(i) == word.charCodeAt(i-2) ) {
					nstate++;
					if ( nstate==3) {
						candidate = word.substring(0,i-1)+word.substring(i+1);
						nsug = testSuggestion( result,candidate, nsug);
						if ( nsug == -1 || nsug == this._maxSug ) return nsug;
						nstate = 0;
					}
				}else {
					nstate=0;
				}
			}
			return nsug;
		}

		private function badchar( result:Array, word:String, nsug:int, capType:int ) :int {
			if ( this._cAllTry == null ) return nsug;
			if (word.length < 2) return nsug;
			var candidate:String;
			var i:int, j:int;			
			switch(capType) {
				case InternalConstants.NOCAP: {
					// first for init capticalized case...
					for ( i = 0; i< this._cAllTry.length;++i) {
						candidate = this._cAllTry.charAt(i)+word.substring(1);
						nsug = testSuggestion( result,candidate, nsug);
						if ( nsug == -1 || nsug == this._maxSug ) return nsug;
					}
					// for the rest of the word...
					for ( i = 0; i< this._cLowerTry.length;++i) {
						for ( j=1;j<word.length;++j) {
							candidate = word.substring(0,j)+this._cLowerTry.charAt(i)+word.substring(j+1);
							nsug = testSuggestion( result,candidate, nsug);
							if ( nsug == -1 || nsug == this._maxSug ) return nsug;
						}
					}
					break;
				}
				case InternalConstants.INITCAP:{
					// first for init capticalized case...
					for ( i = 0; i< this._cAllTry.length;++i) {
						candidate = this._cAllTry.charAt(i)+word.substring(1);
						nsug = testSuggestion( result,candidate, nsug);
						if ( nsug == -1 || nsug == this._maxSug ) return nsug;
					}
					// for the rest of the word...
					for ( i = 0; i< this._cLowerTry.length;++i) {
						for ( j=1;j<word.length;++j) {
							candidate = word.substring(0,j)+this._cLowerTry.charAt(i)+word.substring(j+1);
							nsug = testSuggestion( result,candidate, nsug);
							if ( nsug == -1 || nsug == this._maxSug ) return nsug;
						}
					}
					break;
				}
				case InternalConstants.HUHCAP: { 
				}
				case InternalConstants.HUHINITCAP:{ 
					for ( i = 0; i< this._cAllTry.length;++i) {
						for ( j=0;j<word.length;++j) {
							candidate = word.substring(0,j)+this._cAllTry.charAt(i)+word.substring(j+1);
							nsug = testSuggestion( result,candidate, nsug);
							if ( nsug == -1 || nsug == this._maxSug ) return nsug;
						}
					}
					break;
				}
				case InternalConstants.ALLCAP: {
					for ( i = 0; i< this._cUpperTry.length;++i) {
						for ( j=0;j<word.length;++j) {
							candidate = word.substring(0,j)+this._cUpperTry.charAt(i)+word.substring(j+1);
							nsug = testSuggestion( result,candidate, nsug);
							if ( nsug == -1 || nsug == this._maxSug ) return nsug;
						}
					}
					break;
				}
			}
			
			return nsug;
		}		

		// did we move a char
		private function movechar( result:Array, word:String, nsug:int ) :int {
			var candidate:String;
			var i:int,j:int;
			var char:String;
			if (word.length < 3) return nsug;
			for ( i=0;i<word.length-2;++i) {
				char = word.charAt(i);
				for ( j=i+2;j<word.length;++j) {
					candidate = word.substring(0,i)+word.substring(i+1,j+1)+char+word.substring(j+1);
					nsug = testSuggestion( result,candidate, nsug);
					if ( nsug == -1 || nsug == this._maxSug ) return nsug;
				}
			}
			
			for ( i=word.length-1;i>=2;--i) {
				char = word.charAt(i);
				for ( j=i-2;j>=0; --j) {
					candidate = word.substring(0,j)+char+word.substring(j,i)+word.substring(i+1);
					nsug = testSuggestion( result,candidate, nsug);
					if ( nsug == -1 || nsug == this._maxSug ) return nsug;
				}
			}
			
			return nsug;
		}		

		private function forgotchar( result:Array, word:String, nsug:int, capType:int ) :int {
			if ( this._cAllTry == null ) return nsug;
			var candidate:String;
			var i:int, j:int;			
			if (word.length < 2) return nsug;
			switch(capType) {
				case InternalConstants.NOCAP: {
					for (i =0; i< this._cAllTry.length; ++i ) {
						candidate= _cAllTry.charAt(i) + word.substring(0);
						nsug = testSuggestion( result,candidate, nsug);
						if ( nsug == -1 || nsug == this._maxSug ) return nsug;
					}

					for (i =0; i< this._cLowerTry.length; ++i ) {
						for ( j=1; j< word.length;j++) {
							candidate= word.substring(0,j)+_cLowerTry.charAt(i) + word.substring(j);
							nsug = testSuggestion( result,candidate, nsug);
							if ( nsug == -1 || nsug == this._maxSug ) return nsug;
						}
						candidate= word+_cLowerTry.charAt(i);
						nsug = testSuggestion( result,candidate, nsug);
						if ( nsug == -1 || nsug == this._maxSug ) return nsug;
					}
					break;
				}
				case InternalConstants.INITCAP:{
					// first for init capticalized case...
					for (i =0; i< this._cAllTry.length; ++i ) {
						candidate= _cAllTry.charAt(i) + word.substring(0);
						nsug = testSuggestion( result,candidate, nsug);
						if ( nsug == -1 || nsug == this._maxSug ) return nsug;
					}

					for (i =0; i< this._cLowerTry.length; ++i ) {
						for ( j=1; j< word.length;j++) {
							candidate= word.substring(0,j)+_cLowerTry.charAt(i) + word.substring(j);
							nsug = testSuggestion( result,candidate, nsug);
							if ( nsug == -1 || nsug == this._maxSug ) return nsug;
						}
						candidate= word+_cLowerTry.charAt(i);
						nsug = testSuggestion( result,candidate, nsug);
						if ( nsug == -1 || nsug == this._maxSug ) return nsug;
					}
					break;
				}
				case InternalConstants.HUHCAP: { 
				}
				case InternalConstants.HUHINITCAP:{ 
					for (i =0; i< this._cAllTry.length; ++i ) {
						for ( j=1; j< word.length;j++) {
							candidate= word.substring(0,j)+_cAllTry.charAt(i) + word.substring(j);
							nsug = testSuggestion( result,candidate, nsug);
							if ( nsug == -1 || nsug == this._maxSug ) return nsug;
						}
						candidate= word+_cAllTry.charAt(i);
						nsug = testSuggestion( result,candidate, nsug);
						if ( nsug == -1 || nsug == this._maxSug ) return nsug;
					}
					break;
				}
				case InternalConstants.ALLCAP: {
					for (i =0; i< this._cUpperTry.length; ++i ) {
						for ( j=0; j< word.length;j++) {
							candidate= word.substring(0,j)+_cUpperTry.charAt(i) + word.substring(j);
							nsug = testSuggestion( result,candidate, nsug);
							if ( nsug == -1 || nsug == this._maxSug ) return nsug;
						}
						candidate= word+_cUpperTry.charAt(i);
						nsug = testSuggestion( result,candidate, nsug);
						if ( nsug == -1 || nsug == this._maxSug ) return nsug;
					}
					break;
				}
			}
			return nsug;
		}		

		// error is word has an extra letter it does not need 
		private function extrachar( result:Array, word:String, nsug:int ) :int {
			var candidate:String;
			if (word.length < 2) return nsug;
			for ( var i:int=0; i< word.length ; ++i ) {
				candidate = word.substring(0,i) + word.substring(i+1);
				nsug = testSuggestion( result,candidate, nsug);
				if ( nsug == -1 || nsug == this._maxSug ) return nsug;
			}
			return nsug;
		}		
		
		// error is wrong char in place of correct one (case and keyboard related version)
		private function badcharkey( result:Array, word:String, nsug:int ) :int {
			var candidate:String;
			if (word.length < 2) return nsug;
			var startIndex:int = 0;
			// swap out each char one by one and try uppercase and neighbor
			// keyboard chars in its place to see if that makes a good word
			for ( var i:int =0; i<word.length; ++i) {
				// check with uppercase letters
				if ( word.charAt(i).toLocaleUpperCase() != word.charAt(i) ) {
					candidate = word.substring(0,i)+word.charAt(i).toLocaleUpperCase()+word.substring(i+1);
					nsug = testSuggestion( result,candidate, nsug);
					if ( nsug == -1 || nsug == this._maxSug ) return nsug;
				}
				// check neighbor characters in keyboard string
				if ( this._ckey == null ) continue;
				startIndex = this._ckey.indexOf(word.charAt(i),startIndex);
				while ( startIndex != -1 ) {
					if ( (startIndex!=0) && (_ckey.charAt(startIndex-1) != "|" ) ) {
						candidate = word.substring(0,i)+_ckey.charAt(startIndex-1)+word.substring(i+1);
						nsug = testSuggestion( result,candidate, nsug);
						if ( nsug == -1 || nsug == this._maxSug ) return nsug;
					}
					if ( (_ckey.charAt(startIndex+1)!="|") && (startIndex != _ckey.length - 1) ) {
						candidate = word.substring(0,i)+_ckey.charAt(startIndex+1) + word.substring(i+1);
						nsug = testSuggestion( result,candidate, nsug);
						if ( nsug == -1 || nsug == this._maxSug ) return nsug;
					}
					startIndex = this._ckey.indexOf(word.charAt(i),startIndex+1);
				}
			}
			
			return nsug;
		}		

		private function longswapchar( result:Array, word:String, nsug:int ) :int {
			var candidate:String;
			if (word.length < 2) return nsug;
			for ( var i:int =0 ; i< word.length-2; ++i ) {
				for ( var j:int = i+2;j< word.length;++j) {
					candidate = word.substring(0,i)+ word.charAt(j) + word.substring(i+1,j) + word.charAt(i) + word.substring(j+1);
					nsug = testSuggestion( result,candidate, nsug);
					if ( nsug == -1 || nsug == this._maxSug ) return nsug;
				}
			}
			return nsug;
		}		

		private function swapchar( result:Array, word:String, nsug:int ) :int {
			var candidate:String;
			if (word.length < 2) return nsug;
			var i:int;
			var wl:int = word.length;
			// try swapping adjacent chars one by one
			for (i=0;i< wl-1;++i) {
				candidate = word.substring(0,i)+word.charAt(i+1)+word.charAt(i) + word.substring(i+2);
				nsug = testSuggestion( result,candidate, nsug);
				if ( nsug == -1 || nsug == this._maxSug ) return nsug;
			}
			
			if ( wl == 4 || wl == 5 ) {
				candidate = word.charAt(1) + word.charAt(0);
				if ( wl == 5) candidate +=word.charAt(2);
				candidate += word.charAt(wl - 1) + word.charAt(wl - 2); 
				nsug = testSuggestion( result,candidate, nsug);
				if ( nsug == -1 || nsug == this._maxSug ) return nsug;
				if ( wl == 5 )  {
					candidate = word.charAt(0) + word.charAt(2) + word.charAt(1) + candidate.substr(3);
					nsug = testSuggestion( result,candidate, nsug);
					if ( nsug == -1 || nsug == this._maxSug ) return nsug;
				}
			}
			return nsug;
			
		}		
		private function replchars( result:Array, word:String, nsug:int ) :int {
			var candidate:String;
			if (word.length < 2) return nsug;
			var searchIndex:int=0;
			if ( (this._attributeMgr.simpleFilterTable==null) || (this._attributeMgr.simpleFilterTable.length == 0) ) return nsug;
			for ( var i:int = 0; i < this._attributeMgr.simpleFilterTable.length; ++i ) {
				while ( (searchIndex = word.indexOf( this._attributeMgr.simpleFilterTable[i].matchString,searchIndex)) != -1 ){
					searchIndex = searchIndex + this._attributeMgr.simpleFilterTable[i].matchString.length;
					candidate = word.substr(0, searchIndex-this._attributeMgr.simpleFilterTable[i].matchString.length) + 
					this._attributeMgr.simpleFilterTable[i].replacement + 
					word.substr(searchIndex);
					nsug = testSuggestion( result,candidate, nsug);
					if ( nsug == -1 || nsug == this._maxSug ) return nsug;
				}
				
			}
			return nsug;
		}
		
		private function capchars( result:Array, word:String, nsug:int) : int {
			var candidate:String = word.toLocaleUpperCase();
			return testSuggestion(result,candidate,nsug);
		}
		
		private function testSuggestion(result:Array, word:String, nsug:int):int {
			var cwrd:int=1;
			if ( result.length >= this._maxSug ) return nsug;
			for ( var i:int=0; i < result.length; ++i ) {
				if ( result[i]== word ) cwrd=0;
			}
			
			if ( (cwrd) && checkWord(word) ) {
				result.push(word);
				nsug++;
			}
			return nsug;
		}

		// see if a candidate suggestion is spelled correctly
		// needs to check both root words and words with affixes
		
		// ToDo the following in next release...
		// obsolote MySpell-HU modifications:
		// return value 2 and 3 marks compounding with hyphen (-)
		// `3' marks roots without suffix   

		private function checkWord(word:String):int {
			var rv:HashEntry = null;
			var nosuffix:int =0;
			if ( this._attributeMgr ) {
				rv = _attributeMgr.lookup(word);
				if ( rv ) {
					if ( (rv.affixFlagVector) && ( rv.testAffix(this._attributeMgr.forbiddenWord) || rv.testAffix(this._attributeMgr.noSuggest) )  ){
						return 0;
					}
					while ( rv ) {
						if ( (rv.affixFlagVector) &&  ( rv.testAffix(this._attributeMgr.needAffix) || rv.testAffix(InternalConstants.ONLYUPCASEFLAG) || rv.testAffix(this._attributeMgr.onlyInCompound) )  ) {
							rv = rv.next
						}else break;
					}
				}else rv = _attributeMgr.optPrefixCheck2(word, 0,0) // only prefix, and prefix + suffix XXX
				
				if ( rv ) {
					nosuffix = 1;
				}else {
					rv = _attributeMgr.optSuffixCheck2(word,0,null,0,0);
				}
				//this is added after we have two level suffix stripping
				if (!rv &&  this._attributeMgr.haveContClass) {
					rv = this._attributeMgr.optTwoSuffixCheck(word, 0, null, 0);
					if (!rv) rv = this._attributeMgr.optTwoPrefixCheck(word,1, 0);
				}
				
				// check forbidden words
				if ( (rv) && (rv.affixFlagVector) && ( rv.testAffix(this._attributeMgr.forbiddenWord) || rv.testAffix(InternalConstants.ONLYUPCASEFLAG) 
				|| rv.testAffix(this._attributeMgr.noSuggest) || rv.testAffix(this._attributeMgr.onlyInCompound) ) ) {
					return 0;
				}
				if ( rv ) {
					//// XXX obsolote ToDo
					return 1;
				}
				
			}
			return 0;
		}
		
	}
}

import com.adobe.linguistics.spelling.core.HashEntry;


internal class GuessWord {
	private var _score:int;
	private var _key:String;
	private var _original:String;
	
	public function GuessWord(score:int, key:String, original:String){
		this.key = key;
		this.score = score;
		this.original = original;
	}
	
	public function get score():int {
		return this._score;
	}
	public function set score(value:int) :void {
		this._score = value;
	}
	
	public function get key():String {
		return this._key;
	}
	public function set key(value:String) :void {
		this._key = value;
	}
	public function get original():String {
		return this._original;
	}
	public function set original(value:String) :void {
		this._original = value;
	}
}

internal class SuggestionEntry {
	private var _score:int;
	private var _key:String;
	private var _hashEntry:HashEntry; 
	
	public function SuggestionEntry(score:int, key:String, hashEntry:HashEntry) {
		this.key = key;
		this.score = score;
		this.hashEntry = hashEntry;
		
	}
	
	public function get score():int {
		return this._score;
	}
	public function set score(value:int) :void {
		this._score = value;
	}
	
	public function get key():String {
		return this._key;
	}
	public function set key(value:String) :void {
		this._key = value;
	}
	
	public function get hashEntry():HashEntry {
		return this._hashEntry;
	}
	
	public function set hashEntry(value:HashEntry ) :void {
		this._hashEntry = value;
	}
	
}
