////////////////////////////////////////////////////////////////////////////////
//
//  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.framework.ui
{
	import com.adobe.linguistics.utils.ITokenizer;
	import com.adobe.linguistics.utils.TextTokenizer;
	import com.adobe.linguistics.utils.Token;

	import flash.text.TextField;
	import flash.text.TextFormat;

	import mx.controls.TextArea;
	import mx.controls.TextInput;

	public class HaloWordProcessor implements IWordProcessor
	{
		private var mTextField:TextField;

		public function HaloWordProcessor(textField:TextField)
		{
			if (textField == null ) throw new Error("illegal argument."); 
			mTextField = textField;
		}
				
		
		public function replaceText(token:Token, replacement:String):void {
			var startIndex:int = token.first;
			var endIndex:int = token.last;
			
			if ( replacement == null ) return;
			
			if (mTextField.text.length<endIndex || startIndex<0) {
				return;
			}
			
			var _misspellStart:int = startIndex;
			var _misspellEnd:int = endIndex;
			// Try to preserve the format, this works if the whole misspelled word is the same format
			var tf:TextFormat = mTextField.getTextFormat(_misspellStart, _misspellEnd);
			mTextField.replaceText(_misspellStart, _misspellEnd, replacement);	
			mTextField.setTextFormat(tf, _misspellStart, _misspellStart+replacement.length);
			
			var ta:TextArea = mTextField.parent as TextArea;
			var ti:TextInput = mTextField.parent as TextInput;
			
			if (ta != null) {
				ta.selectionBeginIndex = _misspellStart + replacement.length;
				ta.selectionEndIndex = _misspellStart + replacement.length;
			}
			else if (ti != null) {
				ti.selectionBeginIndex = _misspellStart + replacement.length;
				ti.selectionEndIndex = _misspellStart + replacement.length;				
			}
			else {
				// Do nothing if it's not a valid text component
			}
		}

		
		public function getWordAtPoint(x:uint, y:uint, externalTokenizer:ITokenizer=null):Token
		{
			var _token:Token = tryGetWordAtPoint(x,y, externalTokenizer);
			return _token;
		}
		
		private function tryGetWordAtPoint(x:uint, y:uint, externalTokenizer:ITokenizer=null):Token {
			// TODO: use a better alternative than _misspellStart, end
			var index:uint = mTextField.getCharIndexAtPoint(x + mTextField.scrollH, y);
			if (index >= mTextField.text.length) return null;

			var tmpToken:Token = new Token(index,index);
			var tokenizer:ITokenizer;
			if ( externalTokenizer == null ) {
				tokenizer = new TextTokenizer(mTextField.text);	
			}else {
				tokenizer = externalTokenizer;
			}
			
			var result:Token = new Token(0,0);
			
			var preToken:Token = tokenizer.getPreviousToken(tmpToken);
			var nextToken:Token = tokenizer.getNextToken(tmpToken);
			if ( preToken.last == nextToken.first ) {
				result.first = preToken.first;
				result.last = nextToken.last;
				return result;		
			}else {
				return null;
			}
		}

	}
}