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

	public class OptimizedSuffixEntry  extends AffixEntry
	{
		private var _flagNext:OptimizedSuffixEntry;
		private var _keyNext:OptimizedSuffixEntry;
		private var _flags:Array;
		private var _sfxTable:Array;
		private var _reverseAffixKey:String;
		public function OptimizedSuffixEntry(sfxEntry:SuffixEntry)
		{
			super(sfxEntry.flag,sfxEntry.stripValue,sfxEntry.affixKey,sfxEntry.conditionString,sfxEntry.morphologicalFields, sfxEntry.permissionToCombine, sfxEntry.type,sfxEntry.contclass);
			_flags = new Array();
			_sfxTable = new Array();
			this.nextElementWithFlag = null;
			this.nextElementWithKey = null;
			_flags.push(this.flag);
			_sfxTable.push(sfxEntry);
			this.reverseAffixKey = StringUtils.reverseString(this.affixKey);
			this.flag = -1;
			this.conditionString = "";
		}
		
		public function isSimilarObject(sfxEntry:SuffixEntry):Boolean {
			var chkString:String=this.contclass+sfxEntry.contclass;
			if(chkString)chkString=chkString.split('').sort().join('').replace(/(.)\1+/gi,'$1');//this pattern removes any repetition from strings. this will work only because we are converting n' or q' to Long numbers in decode flags
			if ( (this.stripValue == sfxEntry.stripValue) && (this.affixKey == sfxEntry.affixKey) && (this.permissionToCombine == sfxEntry.permissionToCombine) && (this.morphologicalFields == sfxEntry.morphologicalFields) &&(this.contclass==chkString) )	return true;
			return false;
		} 
		
		public function extendObject( sfxEntry:SuffixEntry ):Boolean {
			
			 if ( !isSimilarObject(sfxEntry) ) return false;
			_flags.push(sfxEntry.flag);
			_sfxTable.push(sfxEntry);
			var newConditionString:String;
			newConditionString = this.conditionPattern.source + "|" + "^"+".*"+sfxEntry.conditionString+"$";
			this.conditionPattern  = new RegExp ( newConditionString);
			//now add in contclass
			this.contclass=sfxEntry.contclass;
			return true;
		}
		
		public function set reverseAffixKey(value:String):void {
			this._reverseAffixKey = value;
		}
		
		public function get reverseAffixKey():String {
			return this._reverseAffixKey;
		}
		
		public function get nextElementWithKey():OptimizedSuffixEntry {
			return this._keyNext;
		}
		
		public function set nextElementWithKey(pfxEntry:OptimizedSuffixEntry):void {
			this._keyNext = pfxEntry;
		}
		
		public function get nextElementWithFlag():OptimizedSuffixEntry {
			return this._flagNext;
		}
		
		public function set nextElementWithFlag(pfxEntry:OptimizedSuffixEntry):void {
			this._flagNext = pfxEntry;
		}
		
		public function get flags():Array {
			return this._flags;
		}
		
		/*
		 * Deprecated function for now...
		 * History: 
		 *          A pre-version of implementation for error detection. 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.
		 */
		// see if this suffix is present in the word
		public function checkWord( word:String, needFlag:int, inCompound:int):HashEntry {
			var disLen:int = word.length - this.affixKey.length;
			var he:HashEntry = null;
			var i:int;

			// upon entry suffix is 0 length or already matches the end of the word.
			// So if the remaining root word has positive length
			// and if there are enough chars in root word and added back strip chars
			// to meet the number of characters conditions, then test it
			if ( (disLen > 0 || (disLen == 0 && this.attributeManager.fullStrip)) ) {
				// generate new root word by removing suffix and adding
				// back any characters that would have been stripped or
				// or null terminating the shorter string
				word = word.substr(0, word.length - this.affixKey.length) + this.stripValue;
				// now make sure all of the conditions on characters
				// are met.  Please see the appendix at the end of
				// this file for more info on exactly what is being
				// tested
				// if all conditions are met then check if resulting
				// root word in the dictionary
				if ( this.conditionPattern.test( word ) ) {
					// look word in hash table
					for ( i=0; i < this.attributeManager.dictionaryManager.dictonaryList.length && !he; ++i ) {
						he = this.attributeManager.dictionaryManager.dictonaryList[i].getElement(word);
						while( he ) {
							if ( he.testAffixs(this._flags) && ( (!needFlag) || he.testAffix(needFlag) ) ) {
								return he;
							}
							he = he.next;
						}
					}
					//if ((opts & aeXPRODUCT) && in_compound)
					if ( this.permissionToCombine ) {
						he = this.attributeManager.optPrefixCheck(word, InternalConstants.aeXPRODUCT,this, needFlag, inCompound);
						if (he) return he; 
					}
				} 
				
			}
			return he;
		}
		
		//for develepors only, function used for printing flags when flag_mode=FLAG.LONG presently not being called anywhere
		public function printFlag(flag:Number):void{
			var result:String =  String.fromCharCode(flag>>8) + String.fromCharCode(flag-((flag>>8)<<8));
			var x:String= this.affixKey;
		}
		// see if this suffix is present in the word
		public function checkWord2( word:String, sfxopts:int, ppfx:AffixEntry, needFlag:int, inCompound:int, cclass:int, pfxcclass:int=0):HashEntry {
			var disLen:int = word.length - this.affixKey.length;
			var he:HashEntry = null;
			var i:int;

			// if this suffix is being cross checked with a prefix
			// but it does not support cross products skip it
			if ( (sfxopts& InternalConstants.aeXPRODUCT) != 0 && this.permissionToCombine != true ) return null;

			// upon entry suffix is 0 length or already matches the end of the word.
			// So if the remaining root word has positive length
			// and if there are enough chars in root word and added back strip chars
			// to meet the number of characters conditions, then test it
			if ( (disLen > 0 || (disLen == 0 && this.attributeManager.fullStrip)) ) {
				// generate new root word by removing suffix and adding
				// back any characters that would have been stripped or
				// or null terminating the shorter string
				word = word.substr(0, word.length - this.affixKey.length) + this.stripValue;
				// now make sure all of the conditions on characters
				// are met.  Please see the appendix at the end of
				// this file for more info on exactly what is being
				// tested
				// if all conditions are met then check if resulting
				// root word in the dictionary
				if ( this.conditionPattern.test( word ) ) {
					// look word in hash table
					for ( i=0; i < this.attributeManager.dictionaryManager.dictonaryList.length && !he; ++i ) {
						he = this.attributeManager.dictionaryManager.dictonaryList[i].getElement(word);
						while( he ) {
							if (  (( he.testAffixs(this._flags) ) && ( (!needFlag) || he.testAffix(needFlag) ))||(ppfx && ppfx.contclass) ) {
								for ( var j:int=0;j<this._sfxTable.length;++j) {
									if ( (this._sfxTable[j] ).conditionPattern.test(word) ) {
										if(!ppfx)
										{
											if(cclass)
											{
												if (he.testAffix(this._flags[j]) && HashEntry.TESTAFF(this.contclass,cclass) )//should handle cases like drink->able->s also in un-run-able-s if run-->able and able-->s and s-->un this should suffice
													return he;
											}
											else											
											{	if(he.testAffix(this._flags[j]))//should handle all normal cases like drink->able or drink->s
												return he;
											}
											
																						
										}
										else
										{
											if(this.contclass && he.testAffix(this._flags[j]) && HashEntry.TESTAFF(this.contclass,cclass) && !pfxcclass) // handle when suffix has contclass like l'->autre->s
											{
											return he;
											}
											if(ppfx.contclass && HashEntry.TESTAFF(ppfx.contclass,this._flags[j]) && he.testAffix(cclass) && !pfxcclass) //handle when prefix has contclass like milli->litre->s
											{
												return he;	
											}
											if(he.testAffix(this._flags[j]) && he.testAffix(cclass))//handle normal cases when both pfx and sfx exist in hash affix string
											{
											return he;
											}
											
											//special case of un-drink-able-s
											if(    (he.testAffix(pfxcclass) && ppfx.contclass && HashEntry.TESTAFF(ppfx.contclass,this._flags[j]) && this.contclass && HashEntry.TESTAFF(this.contclass,cclass)) 
											   ||  (he.testAffix(this._flags[j]) && this.contclass && HashEntry.TESTAFF(this.contclass,cclass) && HashEntry.TESTAFF(this.contclass,pfxcclass))
											   )
											{
												return he;
											}
											
																						
										}
											
										}
								}
							}
							he = he.next;
						}
					}

				} 
				
			}
			return he;
		}
		
		// Function for two level suffix checkword
		// see if this suffix is present in the word
		public function checkTwoWord( word:String, sfxopts:int, ppfx:AffixEntry, needFlag:int, cclass:int, pfxcclass:int=0):HashEntry {
			var disLen:int = word.length - this.affixKey.length;
			var he:HashEntry = null;
			var i:int;
			
			// if this suffix is being cross checked with a prefix
			// but it does not support cross products skip it
			if ( (sfxopts& InternalConstants.aeXPRODUCT) != 0 && this.permissionToCombine != true ) return null;
			
			// upon entry suffix is 0 length or already matches the end of the word.
			// So if the remaining root word has positive length
			// and if there are enough chars in root word and added back strip chars
			// to meet the number of characters conditions, then test it
			if ( (disLen > 0 || (disLen == 0 && this.attributeManager.fullStrip)) ) {
				// generate new root word by removing suffix and adding
				// back any characters that would have been stripped or
				// or null terminating the shorter string
				word = word.substr(0, word.length - this.affixKey.length) + this.stripValue;
				// now make sure all of the conditions on characters
				// are met.  Please see the appendix at the end of
				// this file for more info on exactly what is being
				// tested
				// if all conditions are met then see if for conditional suffix and if this has been stripped by a possible
				// contclass check the remaining word 
				// eg: if drinkables was original word and after possible stripping of s we have drinkable very if 
				// now check drinkable, able will be stripped and drink will be found that hash entry will then be returned
				if ( this.conditionPattern.test( word ) ) {//checks a whole group of 
					
					if(ppfx)
					{ //check for conditional suffix
						if( contclass!=null && HashEntry.TESTAFF(contclass, pfxcclass))
						{
							he = this.attributeManager.optSuffixCheck2(word, 0, null,needFlag,0,cclass,pfxcclass);//we are not sending ppfx here as it will not be needed.
						}
						else
						{
							he = this.attributeManager.optSuffixCheck2(word, sfxopts, ppfx,needFlag,0,cclass,pfxcclass);
						}
					}
					else
					{
						he = this.attributeManager.optSuffixCheck2(word, 0, null,needFlag,0,cclass,0);
					}
					if (he) {
						for ( var j:int=0;j<this._sfxTable.length;++j) { //Squiggly will handle drink->able->s from here
							if ( (this._sfxTable[j]).conditionPattern.test(word) && cclass==(this._sfxTable[j]).flag) {//only permit words which end with s in drinkables
								
									return he;
							
							}
						}
						he = null;
					}
					
				} 
				
			}
			
			return he;
		}
		//--
	}
}