////////////////////////////////////////////////////////////////////////////////
//
//  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 mx.controls.textClasses
{

import flash.text.TextField;
import flash.text.TextFormat;
import mx.core.UIComponent;
import mx.core.mx_internal;
import mx.styles.StyleManager;
import mx.utils.StringUtil;

use namespace mx_internal;

/**
 *  The TextRange class provides properties that select and format a range of
 *  text in the Label, Text, TextArea, TextEditor, and RichTextEditor controls.
 *
 *  @see mx.controls.Label
 *  @see mx.controls.RichTextEditor
 *  @see mx.controls.Text
 *  @see mx.controls.TextArea
 *  @see mx.controls.TextInput
 *  @see flash.text.TextFormatAlign
 *  
 *  @langversion 3.0
 *  @playerversion Flash 9
 *  @playerversion AIR 1.1
 *  @productversion Flex 3
 */
public class TextRange
{
	include "../../core/Version.as";

    //--------------------------------------------------------------------------
    //
    //  Class variables
    //
    //--------------------------------------------------------------------------

	/**
	 *  @private
	 */
	private static var htmlTextField:TextField;

    //--------------------------------------------------------------------------
    //
    //  Constructor
    //
    //--------------------------------------------------------------------------
	
	/**
	 *  Create a new TextRange Object that represents a subset of the contents
	 *  of a text control, including the formatting information.
	 *
	 *  @param owner The control that contains the text. The control must have
	 *  a <code>textField</code> property, or, as is the case of the
	 *  RichTextEditor control, a <code>textArea</code> property.
	 *
	 *  @param modifiesSelection Whether to select the text in the range.
	 *  If you set this parameter to <code>true</code> and do not specify a
	 *  begin or end index that corresponds to text in the control, Flex
	 *  uses the begin or end index of the current text selection.
	 *  If this parameter is <code>true</code>, you omit the
	 *  <code>beginIndex</code> and <code>endIndex</code>
	 *  parameters, and there is no selection, the TextRange object is empty.
	 *
	 *  @param beginIndex Zero-based index of the first character in the range.
	 *  If the <code>modifiesSelection</code> parameter is <code>false</code>
	 *  and you omit this parameter or specify a negative value,
	 *  the range starts with the first text character.
	 *
	 *  @param endIndex Zero-based index of the position <i>after</i> the
	 *  last character in the range.
	 *  If the <code>modifiesSelection</code> parameter is <code>false</code>
	 *  and you omit this parameter, specify a negative value, or specify
	 *  a value past the end of the text, the range ends with the last
	 *  text character.
	 *  
	 *  @langversion 3.0
	 *  @playerversion Flash 9
	 *  @playerversion AIR 1.1
	 *  @productversion Flex 3
	 */
	public function TextRange(owner:UIComponent,
							  modifiesSelection:Boolean = false,
							  beginIndex:int = -1, endIndex:int = -1)
	{
		super();

		_owner = owner;

		try
		{
			textField = _owner["textArea"].getTextField();
		}
		catch(e:Error)
		{
			textField = this["_owner"].getTextField();
		}

		_modifiesSelection = modifiesSelection;

		if (!_modifiesSelection)
		{
			if (beginIndex < 0)
				beginIndex = 0;

			if (beginIndex > textField.length)
				beginIndex = textField.length;

			if (endIndex < 0 || endIndex > textField.length)
				endIndex = textField.length;

			_beginIndex = beginIndex;
			_endIndex = endIndex;
		}
		else
		{
			if (beginIndex < 0 || beginIndex > textField.length)
				beginIndex = textField.selectionBeginIndex;

			if (endIndex < 0 || endIndex > textField.length)
				endIndex = textField.selectionEndIndex;

			textField.selectable = true;
			
			if (beginIndex != textField.selectionBeginIndex ||
				endIndex != textField.selectionEndIndex)
			{
				textField.setSelection(beginIndex, endIndex);
			}
		}
	}

    //--------------------------------------------------------------------------
    //
    //  Variables
    //
    //--------------------------------------------------------------------------

	/**
	 *  @private
	 */
	private var textField:TextField;

    //--------------------------------------------------------------------------
    //
    //  Properties
    //
    //--------------------------------------------------------------------------

    //----------------------------------
	//  beginIndex
    //----------------------------------

	/**
	 *  Storage for the beginIndex property.
	 *  
	 *  @langversion 3.0
	 *  @playerversion Flash 9
	 *  @playerversion AIR 1.1
	 *  @productversion Flex 3
	 */
	private var _beginIndex:int;

	/**
	 *  Zero-based index in the control's text field of the first
	 *  character in the range.
	 *  If the fifth character in the text is the first character in the
	 *  range, this property has a value of 4.
	 *  
	 *  @langversion 3.0
	 *  @playerversion Flash 9
	 *  @playerversion AIR 1.1
	 *  @productversion Flex 3
	 */
	public function get beginIndex():int
	{
		if (_modifiesSelection)
			return textField.selectionBeginIndex;
		else
			return _beginIndex;
	}

	/**
	 *  @private
	 */
	public function set beginIndex(value:int):void
	{
		if (_modifiesSelection)
			textField.setSelection(value, textField.selectionEndIndex);
		else
			_beginIndex = value;
	}

    //----------------------------------
	//  bullet
    //----------------------------------

	/**
	 *  Whether the text in the range is in a bulleted list.
	 *  If only part of the range is in a bulleted list,
	 *  this value is <code>false</code>.
	 *  
	 *  @langversion 3.0
	 *  @playerversion Flash 9
	 *  @playerversion AIR 1.1
	 *  @productversion Flex 3
	 */
	public function get bullet():Boolean
	{
		return getTextFormat().bullet;
	}

	/**
	 *  @private
	 */
	public function set bullet(value:Boolean):void
	{
		var tf:TextFormat = getTextFormat();
		tf.bullet = value;
		setTextFormat(tf);
	}

    //----------------------------------
	//  color
    //----------------------------------

	/**
	 *  Color of the text in the range.
	 *  You can set this value using any valid color identifier.
	 *  The property returns the value as a numeric value.
	 *  If the range has multiple colors, this value is <code>null</code>.
	 *  
	 *  @langversion 3.0
	 *  @playerversion Flash 9
	 *  @playerversion AIR 1.1
	 *  @productversion Flex 3
	 */
	public function get color():Object
	{
		return getTextFormat().color;
	}

	/**
	 *  @private
	 */
	public function set color(value:Object):void
	{
		var tf:TextFormat = getTextFormat();
		var colorNumber:uint = owner.styleManager.getColorName(value);
		if (colorNumber != StyleManager.NOT_A_COLOR)
			value = colorNumber;
		else
			value = 0;
		tf.color = value;
		setTextFormat(tf);
	}

    //----------------------------------
	//  endIndex
    //----------------------------------

	/**
	 *  Storage for the beginIndex property.
	 *  
	 *  @langversion 3.0
	 *  @playerversion Flash 9
	 *  @playerversion AIR 1.1
	 *  @productversion Flex 3
	 */
	private var _endIndex:int;

	/**
	 *  Zero-based index in the control's text field of the point
	 *  immediately after the last character in the range; equivalent to
	 *  the One-based index of the last character. 
	 *  If the fifth character in the text is the last character in the
	 *  range, this property has a value of 5.
	 *  
	 *  @langversion 3.0
	 *  @playerversion Flash 9
	 *  @playerversion AIR 1.1
	 *  @productversion Flex 3
	 */
	public function get endIndex():int
	{
		if (_modifiesSelection)
			return textField.selectionEndIndex;
		else
			return _endIndex;
	}

	/**
	 *  @private
	 */
	public function set endIndex(value:int):void
	{
		if (_modifiesSelection)
			textField.setSelection(textField.selectionBeginIndex, value);
		else
			_endIndex = value;
	}

    //----------------------------------
	//  fontFamily
    //----------------------------------

	/**
	 *  Name of the font for text in the range.
	 *  If the range has multiple fonts, this value is <code>null</code>.
	 *  
	 *  @langversion 3.0
	 *  @playerversion Flash 9
	 *  @playerversion AIR 1.1
	 *  @productversion Flex 3
	 */
	public function get fontFamily():String
	{
		return getTextFormat().font;
	}

	/**
	 *  @private
	 */
	public function set fontFamily(value:String):void
	{
		var tf:TextFormat = getTextFormat();
		tf.font = StringUtil.trimArrayElements(value,",");
		setTextFormat(tf);
	}

    //----------------------------------
	//  fontSize
    //----------------------------------

	/**
	 *  Point size of the text in the range.
	 *  If the range has multiple sizes, this value is 0.
	 *  
	 *  @langversion 3.0
	 *  @playerversion Flash 9
	 *  @playerversion AIR 1.1
	 *  @productversion Flex 3
	 */
	public function get fontSize():int
	{
		return int(getTextFormat().size);
	}

	/**
	 *  @private
	 */
	public function set fontSize(value:int):void
	{
		var tf:TextFormat = getTextFormat();
		tf.size = value;
		setTextFormat(tf);
	}

    //----------------------------------
	//  fontStyle
    //----------------------------------

	/**
	 *  Style of the font in the range, as "italic"
	 *  or "normal". Setting the property to any other string results
	 *  in normal style.
	 *  If the range has multiple styles, this value is <code>null</code>.
	 *  
	 *  @langversion 3.0
	 *  @playerversion Flash 9
	 *  @playerversion AIR 1.1
	 *  @productversion Flex 3
	 */
	public function get fontStyle():String
	{
		return getTextFormat().italic ? "italic" : "normal";
	}

	/**
	 *  @private
	 */
	public function set fontStyle(value:String):void
	{
		var tf:TextFormat = getTextFormat();
		tf.italic = (value == "italic") ? true : false;
		setTextFormat(tf);
	}

    //----------------------------------
	//  fontWeight
    //----------------------------------

	/**
	 *  Weight of the font in the range, as "bold"
	 *  or "normal". Setting the property to any other string results
	 *  in normal weight.
	 *  If the range has multiple weights, this value is <code>null</code>.
	 *  
	 *  @langversion 3.0
	 *  @playerversion Flash 9
	 *  @playerversion AIR 1.1
	 *  @productversion Flex 3
	 */
	public function get fontWeight():String
	{
		return getTextFormat().bold ? "bold" : "normal";
	}

	/**
	 *  @private
	 */
	public function set fontWeight(value:String):void
	{
		var tf:TextFormat = getTextFormat();
		tf.bold = (value == "bold") ? true : false;
		setTextFormat(tf);
	}

    //----------------------------------
	//  htmlText
    //----------------------------------

	/**
	 *  Contents of the range in the form of HTML text.
	 *  This property returns all HTML markup for the range, including
	 *  markup for formatting that is applied by Flex, not just
	 *  HTML that you specify in using an <code>htmlText</code> property.
	 *  This property is, therefore, a full HTML representation of the
	 *  text as it appears in the control.
	 *  
	 *  @langversion 3.0
	 *  @playerversion Flash 9
	 *  @playerversion AIR 1.1
	 *  @productversion Flex 3
	 */
	public function get htmlText():String
	{
		if (beginIndex == endIndex)
			return "";
		
		if (!htmlTextField)
		{
			htmlTextField = new TextField();
			htmlTextField.multiline = true;
		}

		htmlTextField.defaultTextFormat = textField.defaultTextFormat;
		htmlTextField.htmlText = "";

		htmlTextField.insertXMLText(
			0, 0, textField.getXMLText(beginIndex, endIndex))

		return htmlTextField.htmlText;
	}

	/**
	 *  @private
	 */
	public function set htmlText(value:String):void
	{
		
		if (!htmlTextField)
		{
			htmlTextField = new TextField();
			htmlTextField.multiline = true;
		}

		htmlTextField.defaultTextFormat = textField.defaultTextFormat;
		htmlTextField.htmlText = value;
		var length:int = htmlTextField.length;

		var oldBeginIndex:int = beginIndex;
		textField.insertXMLText(
			beginIndex, endIndex, htmlTextField.getXMLText());
		// workaround for what seems to be a player bug (#207147)
		// where a zero length selection is shifted
		// (if no bug, this code should never execute)
		if ((oldBeginIndex == 0) && (beginIndex > 0))
			beginIndex = 0;
		
		endIndex = beginIndex + length;
	}

    //----------------------------------
	//  kerning
    //----------------------------------

	/**
	 *  A Boolean value that indicates whether kerning
	 *  is enabled (<code>true</code>) or disabled (<code>false</code>).
	 *  Kerning adjusts the pixels between certain character pairs
	 *  to improve readability, and should be used only when necessary,
	 *  such as with headings in large fonts.
	 *  Kerning is supported for embedded fonts only. 
	 *  Certain fonts, such as Verdana, and monospaced fonts,
	 *  such as Courier New, do not support kerning.
	 *
	 *  @default false
	 *  
	 *  @langversion 3.0
	 *  @playerversion Flash 9
	 *  @playerversion AIR 1.1
	 *  @productversion Flex 3
	 */
	public function get kerning():Boolean
	{
		return Boolean(getTextFormat().kerning);
	}

	/**
	 *  @private
	 */
	public function set kerning(value:Boolean):void
	{
		var tf:TextFormat = getTextFormat();
		tf.kerning = value;
		setTextFormat(tf);
	}

    //----------------------------------
	//  letterSpacing
    //----------------------------------

	/**
	 *  The number of additional pixels to appear between each character.
	 *  A positive value increases the character spacing
	 *  beyond the normal spacing, while a negative value decreases it.
	 * 
	 *  @default 0
	 *  
	 *  @langversion 3.0
	 *  @playerversion Flash 9
	 *  @playerversion AIR 1.1
	 *  @productversion Flex 3
	 */
	public function get letterSpacing():Number
	{
		return Number(getTextFormat().letterSpacing);
	}

	/**
	 *  @private
	 */
	public function set letterSpacing(value:Number):void
	{
		var tf:TextFormat = getTextFormat();
		tf.letterSpacing = value;
		setTextFormat(tf);
	}

    //----------------------------------
	//  modifiesSelection
    //----------------------------------

	/**
	 *  @private
	 *  Storage for the modifiesSelection property.
	 */
	private var _modifiesSelection:Boolean;

	/**
	 *  Whether the TextRange modifies the currenly selected text.
	 *  Set by the constructor.
	 *  
	 *  @langversion 3.0
	 *  @playerversion Flash 9
	 *  @playerversion AIR 1.1
	 *  @productversion Flex 3
	 */
	public function get modifiesSelection():Boolean
	{
		return _modifiesSelection;
	}

    //----------------------------------
	//  owner
    //----------------------------------

	/**
	 *  @private
	 *  Storage for the owner property.
	 */
	private var _owner:UIComponent;

	/**
	 *  The control that contains the text.
	 *  The owner control must have a <code>textField</code> property,
	 *  or, as is the case of the RichTextEditor control,
	 *  a <code>textArea</code> property.
	 *  The owner of the text in a RichTextEditor control is the
	 *  RichTextEditor control, not its TextArea subcontrol.
	 *  Initially set by the constructor.
	 *  
	 *  @langversion 3.0
	 *  @playerversion Flash 9
	 *  @playerversion AIR 1.1
	 *  @productversion Flex 3
	 */
	public function get owner():UIComponent
	{
		return _owner;
	}

	/**
	 *  @private
	 */
	public function set owner(value:UIComponent):void
	{
		_owner = value;

		try
		{
			textField = _owner["textArea"]["textField"];
		}
		catch(e:Error)
		{
			textField = _owner["textField"];
		}
	}

    //----------------------------------
	//  text
    //----------------------------------

	/**
	 *  Plain-text contents of the range.
	 *  
	 *  @langversion 3.0
	 *  @playerversion Flash 9
	 *  @playerversion AIR 1.1
	 *  @productversion Flex 3
	 */
	public function get text():String
	{
		return textField.text.substring(beginIndex, endIndex);
	}

	/**
	 *  @private
	 */
	public function set text(value:String):void
	{
		var oldBeginIndex:int = beginIndex;
		textField.replaceText(beginIndex,endIndex,value);
		// workaround for what seems to be a player bug (#207147)
		// where a zero length selection is shifted
		// (if no bug, this code should never execute)
		if ((oldBeginIndex == 0) && (beginIndex > 0))
			beginIndex = 0;
		endIndex = beginIndex + value.length;
	}

    //----------------------------------
	//  textAlign
    //----------------------------------

	/**
	 *  Alignment of the text in the range.
	 *  The flash.text.TextFormatAlign constants specify the valid values.
	 *  Setting this property to any other value has no effect.
	 *  If the range has multiple alignments, this value is <code>null</code>.
	 * 
	 *  @see flash.text.TextFormatAlign
	 *  
	 *  @langversion 3.0
	 *  @playerversion Flash 9
	 *  @playerversion AIR 1.1
	 *  @productversion Flex 3
	 */
	public function get textAlign():String
	{
		return getTextFormat().align;
	}

	/**
	 *  @private
	 */
	public function set textAlign(value:String):void
	{
		var tf:TextFormat = getTextFormat();
		tf.align = value;
		setTextFormat(tf);
	}

    //----------------------------------
	//  textDecoration
    //----------------------------------

	/**
	 *  Decoration of the font in the range, as "underline"
	 *  or "normal". Setting the property to any other string results
	 *  in normal text.
	 *  If the range has multiple decoration settings, this value is
	 *  <code>null</code>.
	 *  
	 *  @langversion 3.0
	 *  @playerversion Flash 9
	 *  @playerversion AIR 1.1
	 *  @productversion Flex 3
	 */
	public function get textDecoration():String
	{
		return getTextFormat().underline ? "underline" : "normal";
	}

	/**
	 *  @private
	 */
	public function set textDecoration(value:String):void
	{
		var tf:TextFormat = getTextFormat();
		tf.underline = (value == "underline") ? true : false;
		setTextFormat(tf);
	}

    //----------------------------------
	//  url
    //----------------------------------

	/**
	 *  URL for a hypertext link in the range.
	 *  If the range does not include a link, the value
	 *  is the empty string.
	 *  If the range includes multiple links, the value
	 *  is <code>null</code>.
	 *  
	 *  @langversion 3.0
	 *  @playerversion Flash 9
	 *  @playerversion AIR 1.1
	 *  @productversion Flex 3
	 */
	public function get url():String
	{
		return getTextFormat().url;
	}

	/**
	 *  @private
	 */
	public function set url(value:String):void
	{
		var tf:TextFormat = getTextFormat();

		if (value != "")
		{
			tf.url = value;
			tf.target = "_blank";
		}
		else if (tf.url != "")
		{
			tf.url = "";
			tf.target = "";
		}

		setTextFormat(tf);
	}

    //--------------------------------------------------------------------------
    //
    //  Methods
    //
    //--------------------------------------------------------------------------

	/**
	 *  @private
	 */
	private function getTextFormat():TextFormat
	{
		var tf:TextFormat;
		if (_modifiesSelection && beginIndex == endIndex)
			tf = textField.defaultTextFormat;
		else
			tf = textField.getTextFormat(beginIndex, endIndex);
		return tf;
	}

	/**
	 *  @private
	 */
	private function setTextFormat(tf:TextFormat):void
	{
		if (_modifiesSelection && beginIndex == endIndex)
			textField.defaultTextFormat = tf;
		else
			textField.setTextFormat(tf,beginIndex, endIndex);
	}
}

}