////////////////////////////////////////////////////////////////////////////////
//
//  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 flashx.textLayout.factory
{
	import flash.display.Shape;
	import flash.display.Sprite;
	import flash.geom.Rectangle;
	import flash.text.engine.TextBlock;
	import flash.text.engine.TextLine;
	import flash.text.engine.TextLineValidity;
	
	import flashx.textLayout.compose.IFlowComposer;
	import flashx.textLayout.compose.ISWFContext;
	import flashx.textLayout.compose.SimpleCompose;
	import flashx.textLayout.compose.StandardFlowComposer;
	import flashx.textLayout.container.ContainerController;
	import flashx.textLayout.container.ScrollPolicy;
	import flashx.textLayout.debug.Debugging;
	import flashx.textLayout.debug.assert;
	import flashx.textLayout.elements.OverflowPolicy;
	import flashx.textLayout.elements.TextFlow;
	import flashx.textLayout.formats.BlockProgression;
	import flashx.textLayout.tlf_internal;
	
	use namespace tlf_internal;

	[Exclude(name="containerController",kind="property")]	
	[Exclude(name="setContentBounds",kind="method")]
	[Exclude(name="callbackWithTextLines",kind="method")]
	[Exclude(name="doesComposedTextFit",kind="method")]
	[Exclude(name="getNextTruncationPosition",kind="method")]


/**
 * The TextLineFactoryBase class serves as the base class for the Text Layout Framework text line factories.
 * 
 * <p><b>Note:</b> Application code does not typically need to create or use a TextLineFactoryBase object directly.
 * Use one of the derived text factory classes instead.</p>
 *  
 * @playerversion Flash 10
 * @playerversion AIR 1.5
 * @langversion 3.0
 *
 * @see flashx.textLayout.elements.TextFlow
*/
	public class TextLineFactoryBase
	{
		/** Requested logical bounds to wrap to */
		private var _compositionBounds:Rectangle;

		/** Bounds of composition results - where the text landed */
		private var _contentBounds:Rectangle;
		
		/** @private */
		protected var _isTruncated:Boolean = false;
		
		private var _horizontalScrollPolicy:String;
		private var _verticalScrollPolicy:String;
		private var _truncationOptions:TruncationOptions;
		private var _containerController:ContainerController;
		static private var _tc:Sprite = new Sprite();
		
		private var _swfContext:ISWFContext;
		
		/** @private */
		static private      var _savedFactoryComposer:SimpleCompose;
		/** @private */
		static tlf_internal var _factoryComposer:SimpleCompose;

		/** @private */		
		protected var _truncationLineIndex:int; 	// used during truncation
		/** @private */		
		protected var _pass0Lines:Array; 		// used during truncation
		
		/** @private return the next factory composer that will be used */
		static tlf_internal function peekFactoryCompose():SimpleCompose
		{
			if (_savedFactoryComposer == null)
				_savedFactoryComposer = new SimpleCompose();
			return _savedFactoryComposer;
		}
		
		/** @private support recursive calls into the factory */
		static tlf_internal function beginFactoryCompose():SimpleCompose
		{
			var rslt:SimpleCompose = _factoryComposer;
			_factoryComposer = peekFactoryCompose();
			_savedFactoryComposer = null;
			return rslt;
		}
		
		/** @private support recursive calls into the factory */
		static tlf_internal function endFactoryCompose(prevComposer:SimpleCompose):void
		{
			_savedFactoryComposer = _factoryComposer;
			_factoryComposer = prevComposer;
		}
		
		/** 
		 * Base-class constructor for text line factories.
		 *  
 		 * <p><b>Note:</b> Application code does not typically need to create or use a TextLineFactoryBase object directly.
		 * Use one of the derived text factory classes instead.</p>
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 */
		public function TextLineFactoryBase()
		{
			_containerController = new ContainerController(_tc);
			_horizontalScrollPolicy = _verticalScrollPolicy = String(ScrollPolicy.scrollPolicyPropertyDefinition.defaultValue);
		}
		
		/**
		 * The rectangle within which text lines are created.
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 */
		public function get compositionBounds():Rectangle
		{
			return _compositionBounds;
		}
		
		public function set compositionBounds(value:Rectangle):void
		{
			_compositionBounds = value;
		}
		
		/**
		 * The smallest rectangle in which the layed-out content fits.
		 * 
		 * <p><b>Note:</b> Truncated lines are not included in the size calculation.</p>
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 */
		public function getContentBounds():Rectangle
		{
			return _contentBounds;
		}
		
		/** @private */
		protected function setContentBounds(controllerBounds:Rectangle):void
		{
			_contentBounds = controllerBounds;
			_contentBounds.offset(compositionBounds.left, compositionBounds.top);
		}
		
		/** 
		* The ISWFContext instance used to make FTE calls as needed. 
		*
		* <p>By default, the ISWFContext implementation is this FlowComposerBase object.
		* Applications can provide a custom implementation to use fonts
		* embedded in a different SWF file or to cache and reuse text lines.</p>
		* 
		* @see flashx.textLayout.compose.ISWFContext
		* 
		* @playerversion Flash 10
		* @playerversion AIR 1.5
	 	* @langversion 3.0
	 	*/
 	
		public function get swfContext():ISWFContext
		{
			return _swfContext;
		}
		public function set swfContext(value:ISWFContext):void
		{
			_swfContext = value;
		}
		
		/** 
		 * Specifies the options for truncating the text if it doesn't fit in the composition bounds.
		 *  
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 */
		public function get truncationOptions():TruncationOptions
		{
			return _truncationOptions;
		}
		public function set truncationOptions(value:TruncationOptions):void
		{
			_truncationOptions = value;
		}
		
		/** 
		 * Indicates whether text was truncated when lines were last created.
		 *  
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 */
		public function get isTruncated():Boolean
		{
			return _isTruncated;
		}

		/** 
		 * Specifies how lines are created when the composition bounds are not large enough.
		 *  
		 * <p>If set to <code>ScrollPolicy.ON</code> or <code>ScrollPolicy.AUTO</code>, all lines
		 * are created. It is the your responsibility to scroll lines in the viewable area (and to
		 * mask lines outside this area, if necessary). If set to <code>ScrollPolicy.OFF</code>, then 
		 * only lines that fit within the composition bounds are created.</p>
		 * 
		 * <p>If the <code>truncationOptions</code> property is set, the scroll policy is ignored 
		 * (and treated as <code>ScrollPolicy.OFF</code>).</p> 
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 * 
		 * @see flashx.textLayout.compose.StandardFlowComposer
		 * @see flashx.textLayout.container.ScrollPolicy
		 * @see #truncationOptions
	 	 */
	 	 
	 	public function get horizontalScrollPolicy():String
		{
			return _horizontalScrollPolicy;
		}
		public function set horizontalScrollPolicy(scrollPolicy:String):void
		{
			_horizontalScrollPolicy =  scrollPolicy;
		}
		
		/** 
		 * Specifies how lines are created when the composition bounds are not large enough.
		 *  
		 * <p>If set to <code>ScrollPolicy.ON</code> or <code>ScrollPolicy.AUTO</code>, all lines
		 * are created. It is the your responsibility to scroll lines in the viewable area (and to
		 * mask lines outside this area, if necessary). If set to <code>ScrollPolicy.OFF</code>, then 
		 * only lines that fit within the composition bounds are created.</p>
		 * 
		 * <p>If the <code>truncationOptions</code> property is set, the scroll policy is ignored 
		 * (and treated as <code>ScrollPolicy.OFF</code>).</p> 
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 * 
		 * @see flashx.textLayout.compose.StandardFlowComposer
		 * @see flashx.textLayout.container.ScrollPolicy
		 * @see #truncationOptions
	 	 */
	 	 
		public function get verticalScrollPolicy():String
		{
			return _verticalScrollPolicy;
		}
		public function set verticalScrollPolicy(scrollPolicy:String):void
		{
			_verticalScrollPolicy =  scrollPolicy;
		}		
		
		/** @private */
		tlf_internal static function getDefaultFlowComposerClass():Class
		{
			return FactoryDisplayComposer;
		}
		
		/** @private */
		protected function get containerController():ContainerController
		{
			return _containerController;
		}
		
		/** 
		 * Sends the created TextLine objects to the client using the supplied callback function.
		 * 
		 * <p>This method sets the <code>x</code> and <code>y</code> properties of the line.</p>
		 * 
		 * @param callback the callback function supplied by the factory user
		 * @param delx the horizontal offset
		 * @param dely the vertical offset
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 */
		protected function callbackWithTextLines(callback:Function,delx:Number,dely:Number):void
		{
			for each (var textLine:TextLine in _factoryComposer._lines)
			{
				var textBlock:TextBlock = textLine.textBlock;
				if (textBlock)
				{
					CONFIG::debug { Debugging.traceFTECall(null,textBlock,"releaseLines",textBlock.firstLine, textBlock.lastLine); }	
					textBlock.releaseLines(textBlock.firstLine,textBlock.lastLine);
				}
				textLine.userData = null;
				textLine.x += delx;
				textLine.y += dely;
				textLine.validity = TextLineValidity.STATIC;
				CONFIG::debug { Debugging.traceFTEAssign(textLine,"validity",TextLineValidity.STATIC); }
				callback(textLine);
			}
		}
		
		/**
		 * Indicates whether the composed text fits in the line count limit and includes all text
		 *  
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 */	
		protected function doesComposedTextFit (lineCountLimit:int, textLength:uint, blockProgression:String):Boolean
		{
			if (lineCountLimit != TruncationOptions.NO_LINE_COUNT_LIMIT && _factoryComposer._lines.length > lineCountLimit)
				return false; // Line count limit exceded
			
			var lines:Array = _factoryComposer._lines;
		
			if (!lines.length)
				return textLength ? false /* something to compose, but no line could fit */ : true /* nothing to compose */; 
				
			// This code is only called when scrolling if OFF, so only lines that fit in bounds are generated
			// Just check if the last line reaches the end of flow
			var lastLine:TextLine = lines[lines.length - 1] as TextLine;
			return lastLine.userData + lastLine.rawTextLength == textLength;
		}
		
		/** 
		 * Gets the next truncation position by shedding an atom's worth of characters.
		 * 
		 * @param truncateAtCharPosition the current truncation candidate position.
		 * @param multiPara <code>true</code> if text has more than one paragraph.
		 * 
		 * @returns the next candidate truncation position.
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 */
		protected function getNextTruncationPosition(truncateAtCharPosition:int, multiPara:Boolean=false):int
		{
			// 1. Get the position of the last character of the preceding atom
			truncateAtCharPosition--; // truncateAtCharPosition-1, because truncateAtCharPosition is an atom boundary
			
			// Note: The current set of lines may not contain the next truncation position because the truncation indicator
			// could combine with original content to form a word that does not afford a suitable break opportunity. 
			// The combined word would then move to the next line, which may not have been composed if the bounds were exceeded.
			// Therefore, this function needs to use the original lines (from before truncation is attempted). 
			CONFIG::debug 
			{ 
				assert(_pass0Lines != null, "getNextTruncationPosition called before saving off lines from the first pass at composition"); 
				assert(_truncationLineIndex < _pass0Lines.length, "index out of range in getNextTruncationPosition");
			}
			
			// 2. Find the new target line (i.e., the line that has the new truncation position) 
			// If the last truncation position was at the beginning of the target line, the new position may have moved to a previous line
			// In any case, the new truncation position lies in the vicinity of the previous target line, so a linear search suffices
			var line:TextLine = _pass0Lines[_truncationLineIndex] as TextLine;
			do
			{
				if (truncateAtCharPosition >= line.userData && truncateAtCharPosition < line.userData + line.rawTextLength)
					break;
				if (truncateAtCharPosition < line.userData)
					line = _pass0Lines[--_truncationLineIndex] as TextLine;
				else
				{
					CONFIG::debug {	assert(false, "truncation position should decrease monotonically");	}
				}	
			}
			while (true);

			var paraStart:int = multiPara ?  line.userData - line.textBlockBeginIndex : 0;
			
			// 3. Get the line atom index at this position			
			var atomIndex:int = line.getAtomIndexAtCharIndex(truncateAtCharPosition - paraStart);
			
			// 4. Get the char index for this atom index
			var nextTruncationPosition:int = line.getAtomTextBlockBeginIndex(atomIndex) + paraStart;
			
			//line.flushAtomData(); // Warning: Now does nothing
			
			return nextTruncationPosition;
		} 
		/** @private */
		tlf_internal function createFlowComposer():IFlowComposer
		{
			return new FactoryDisplayComposer();
		}			
		
		/** @private
		 * Calculates the last line that fits in the line count limit
		 * The result is stored in  _truncationLineIndex
		 * 
		 * Note: This code is only called when scrolling is OFF, so only lines that fit in bounds are generated
		 */
		tlf_internal function computeLastAllowedLineIndex (lineCountLimit:int):void
		{			
			_truncationLineIndex = _factoryComposer._lines.length - 1;

			// if line count limit is smaller, use that
			if (lineCountLimit != TruncationOptions.NO_LINE_COUNT_LIMIT && lineCountLimit <= _truncationLineIndex)
				_truncationLineIndex = lineCountLimit - 1;
		}
		
		
		/** @private helper to process the background colors.  default implementation creates a shape and passes it to the callback */
		tlf_internal function processBackgroundColors(textFlow:TextFlow,callback:Function,x:Number,y:Number,constrainWidth:Number,constrainHeight:Number):*
		{
			CONFIG::debug { assert(textFlow.backgroundManager != null,"Bad call to processBackgroundColors"); }
			var bgShape:Shape = new Shape();
			textFlow.backgroundManager.drawAllRects(textFlow,bgShape,constrainWidth,constrainHeight);
			bgShape.x = x;
			bgShape.y = y;
			callback(bgShape);
			textFlow.clearBackgroundManager();
		}
	}

} // end package







