////////////////////////////////////////////////////////////////////////////////
//
//  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.container
{
	import flash.geom.Rectangle;
	
	import flashx.textLayout.debug.assert;
	import flashx.textLayout.elements.TableDataCellElement;
	import flashx.textLayout.formats.BlockProgression;
	import flashx.textLayout.formats.Direction;
	import flashx.textLayout.formats.FormatValue;
	import flashx.textLayout.formats.ITextLayoutFormat;
	import flashx.textLayout.formats.LineBreak;
	import flashx.textLayout.tlf_internal;
	import flashx.textLayout.utils.Twips;
		
	use namespace tlf_internal;

	/** 
	 * The ColumnState class calculates the sizes and locations of columns using
	 * the width of the container and the container attributes. You can create instances of this class 
	 * independently to calculate column values, or you can get the column values that 
	 * were used for the text after the container has been composed or updated (redrawn).
	 *
	 * @playerversion Flash 10
	 * @playerversion AIR 1.5
	 * @langversion 3.0
	 *
	 * @see ContainerController
	 */

	public class ColumnState 
	{
		// input information
		private var _inputsChanged:Boolean;
		private var _blockProgression:String;
		private var _columnDirection:String;
		private var _paddingTop:Number;
		private var _paddingBottom:Number;
		private var _paddingLeft:Number;
		private var _paddingRight:Number;
		private var _compositionWidth:Number;
		private var _compositionHeight:Number;
		private var _forceSingleColumn:Boolean;
		
		private var _inputColumnWidth:Object;
		private var _inputColumnGap:Number;
		private var _inputColumnCount:Object
		
		// Generated column information		
		private var _columnWidth:Number;	
		private var _columnCount:int;		
		private var _columnGap:Number;	
		private var _inset:Number;
		
		// and the array of columns
		private var _columnArray:Array;
		private var _tableCellArray:Array;
		private var _singleColumn:Rectangle;
		
		/**
		 * Constructor function - creates a ColumnState object.
		 *
		 * If the values of <code>controller.compositionWidth</code> and <code>controller.compositionHeight</code> equal
		 * <code>NaN</code> (not a number), the constructor measures the container's contents to determine the actual 
		 * composition width and height that feed into ColumnState.
		 *
		 * Use the constants defined by the <code>flashx.textLayout.formats.BlockProgression</code> class to 
		 * specify the value of the <code>blockProgression</code> parameter. Use the constants defined by
		 * <code>flashx.textLayout.formats.Direction</code> to specify the value of the <code>columnDirection</code> 
		 * parameter.
		 *
		 * @param blockProgression The direction of lines for the textflow, either BlockProgression.TB (top-to-bottom) or 
		 * 		BlockProgression.RL (right-to-left).
		 * @param columnDirection The direction of column layout for the text flow, either Direction.RTL (right-to-left) or 
		 * 		Direction.LTR (left-to-right).
		 * @param controller A ContainerController instance whose attributes are used to calculate the column values.
		 * @param compositionWidth The horizontal extent, in pixels, allowed for text inside the container.
		 * @param compositionHeight The vertical extent, in pixels, allowed for text inside the container.
		 *
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 * 
		 * @see flashx.textLayout.formats.BlockProgression BlockProgression
		 * @see flashx.textLayout.formats.Direction Direction
	 	 */
		
		public function ColumnState(blockProgression:String, columnDirection:String, controller:ContainerController, compositionWidth:Number, compositionHeight:Number)
		{
			_inputsChanged = true;
			_columnCount = 0;

			if (blockProgression != null)		// if values are legit, recalculate now. They might not be, if this is called from a containerController constructor.
			{		
				updateInputs(blockProgression, columnDirection, controller, compositionWidth, compositionHeight);
				computeColumns();
			}
		}
		
		/** 
		 * The width of columns, in pixels, in the container. 
		 *
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
	 	 * @langversion 3.0
	 	 */
	 	 
		public function get columnWidth():Number
		{ return _columnWidth; }

		/** 
		 * The number of columns in the container. 
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
	 	 * @langversion 3.0
	 	 */
	 	 
		public function get columnCount():int
		{ return _columnCount; }
		
		/** 
		 * The number of cells in the container. 
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 */
		
		public function get cellCount():int
		{ 
			if ( _tableCellArray )
				return _tableCellArray.length;
			return -1;
		}

		/** 
		 * The amount of space, in pixels, left between columns in the container.
		 *
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
	 	 * @langversion 3.0
	 	 */
	 	 
		public function get columnGap():Number
		{ return _columnGap; }
		
		/** 
		 * Returns the area that a column takes within the container. Allows you to access the area for a 
		 * specific column.
		 *
		 * @param index The relative position of the column among all columns in the container, with the first
		 * 	column at position 0.
		 *
		 * @return The area of the specified column.
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
		 * @langversion 3.0
		 */
		 
		public function getColumnAt(index:int):Rectangle
		{
			return _columnCount == 1 ? _singleColumn : _columnArray[index];
		}
		
		public function getCellAt(index:int):TableDataCellElement
		{
			return _tableCellArray[index];
		}
		
		public function pushTableCell(cell:TableDataCellElement):void
		{
			if ( _tableCellArray == null )
				_tableCellArray = new Array();
			_tableCellArray.push(cell);
		}
		
		public function clearCellList():void
		{
			_tableCellArray = null;
		}

		/** Recalculate actual column settings based on attributes and width
		 * from the container. Call this after either the attributes or the
		 * width has been changed to get the new values.
		 *
		 * @param newBlockProgression block progression for the textflow
		 * @param newColumnDirection column layout direction for the textflow
		 * @param containerAttr		Formatting attributes from the container
		 * @param containerWidth		Width of the container
		 * @return Boolean			true if the actual column settings have changed
		 * @private 
		 */
		tlf_internal function updateInputs(newBlockProgression:String, newColumnDirection:String, controller:ContainerController, newCompositionWidth:Number, newCompositionHeight:Number ):void
		{
			var newPaddingTop:Number = controller.getTotalPaddingTop();
			var newPaddingBottom:Number = controller.getTotalPaddingBottom();
			var newPaddingLeft:Number = controller.getTotalPaddingLeft();
			var newPaddingRight:Number = controller.getTotalPaddingRight();
			
			var containerAttr:ITextLayoutFormat = controller.computedFormat;
			
			var newColumnWidth:Object = containerAttr.columnWidth;
			var newColumnGap:Number = containerAttr.columnGap;
			var newColumnCount:Object = containerAttr.columnCount;
			
			var newForceSingleColumn:Boolean = ((containerAttr.columnCount == FormatValue.AUTO && (containerAttr.columnWidth == FormatValue.AUTO || Number(containerAttr.columnWidth) == 0)) ||
				controller.rootElement.computedFormat.lineBreak == LineBreak.EXPLICIT) || isNaN(newBlockProgression == BlockProgression.RL ? newCompositionHeight : newCompositionWidth);
			
			if (_inputsChanged == false) 
				_inputsChanged = newCompositionWidth != _compositionHeight || newCompositionHeight != _compositionHeight
				|| _paddingTop != newPaddingTop || _paddingBottom != newPaddingBottom || _paddingLeft != newPaddingLeft || _paddingRight != newPaddingRight
				|| _blockProgression != _blockProgression || _columnDirection != newColumnDirection || _forceSingleColumn != newForceSingleColumn
				|| _inputColumnWidth != newColumnWidth || _inputColumnGap != newColumnGap || _inputColumnCount != newColumnCount;
				
			if (_inputsChanged)
			{
				_blockProgression = newBlockProgression;
				_columnDirection = newColumnDirection;
				_paddingTop = newPaddingTop;
				_paddingBottom = newPaddingBottom;
				_paddingLeft = newPaddingLeft;
				_paddingRight = newPaddingRight;
				_compositionWidth = newCompositionWidth;
				_compositionHeight = newCompositionHeight;
				_forceSingleColumn = newForceSingleColumn;
				
				_inputColumnWidth = newColumnWidth;
				_inputColumnGap = newColumnGap;
				_inputColumnCount = newColumnCount;
			}
		}

		/** Compute the actual columns based on the input values @private */
		tlf_internal function computeColumns():void
		{
			if (!_inputsChanged)
				return;
				
			// Recalculate all the column settings. Returns true if settings have changed as a result.
			// See http://www.w3.org/TR/2005/WD-css3-multicol-20051215/#the-number
			var newColumnGap:Number;
			var newColumnCount:int;
			var newColumnWidth:Number;
			
			// calculate the width to divy the columns up among
			var totalColumnWidth:Number = _blockProgression == BlockProgression.RL ? _compositionHeight : _compositionWidth;
			// inset to use
			var newColumnInset:Number   = _blockProgression == BlockProgression.RL ? _paddingTop + _paddingBottom : _paddingLeft + _paddingRight;
				
			totalColumnWidth = (totalColumnWidth > newColumnInset && !isNaN(totalColumnWidth)) ? totalColumnWidth - newColumnInset : 0;
			
			// columnCount is auto && columnWidth is auto || 0 --> one column
			if (_forceSingleColumn)
			{
				// This case deviates from the spec.  Spec is no columns.  
				// TextLayout does either one auto full width column or a zero width column
				newColumnCount = 1;
				newColumnWidth = totalColumnWidth; 
				newColumnGap = 0;
			}
			else
			{
				newColumnGap   = _inputColumnGap;
				
				if (_inputColumnWidth == FormatValue.AUTO)		// auto
				{
					newColumnCount = Number(_inputColumnCount);
					// Column width is not specified, we'll use columnCount and columnGap to figure it out
					if ((newColumnCount-1)*newColumnGap < totalColumnWidth)
					{
						newColumnWidth = (totalColumnWidth - (newColumnCount-1)*newColumnGap) / newColumnCount;
					}
					else if (newColumnGap > totalColumnWidth)
					{
						newColumnCount = 1;
						newColumnWidth = totalColumnWidth;
						newColumnGap = 0;
					}
					else
					{
						newColumnCount = Math.floor(totalColumnWidth/newColumnGap);
						newColumnWidth = (totalColumnWidth-(newColumnCount-1)*newColumnGap)/newColumnCount;
						// newColumnGap = newColumnCount == 1 ? 0 : (totalColumnWidth - newColumnWidth*newColumnCount) / (newColumnCount-1);
					}
				}
				else if (_inputColumnCount == FormatValue.AUTO)	// auto
				{
					newColumnWidth = Number(_inputColumnWidth);
					if (newColumnWidth >= totalColumnWidth)
					{
						newColumnCount = 1;
						newColumnWidth = totalColumnWidth;
						newColumnGap   = 0;
					}
					else
					{
						newColumnCount = Math.floor((totalColumnWidth+newColumnGap)/(newColumnWidth+newColumnGap));
						newColumnWidth = ((totalColumnWidth+newColumnGap)/newColumnCount) - newColumnGap;
					}
				}
				else
				{
					newColumnCount = Number(_inputColumnCount);
					newColumnWidth = Number(_inputColumnWidth);
					if (newColumnCount*newColumnWidth+(newColumnCount-1)*newColumnGap <= totalColumnWidth)
					{
						// done
					}
					else if (newColumnWidth >= totalColumnWidth)
					{
						newColumnCount = 1;
						newColumnGap = 0;
						// use newColumnWidth
					}
					else
					{
						newColumnCount = Math.floor( (totalColumnWidth+newColumnGap) / (newColumnWidth+newColumnGap) );
						newColumnWidth = ((totalColumnWidth+newColumnGap) / newColumnCount) - newColumnGap;
					}
				}
			}
				
			_columnWidth = newColumnWidth;
			_columnCount = newColumnCount;
			_columnGap = newColumnGap;
			_inset = newColumnInset;			
	
			// setup these values for each case
			var xPos:Number;
			var yPos:Number;
			var delX:Number;
			var delY:Number;
			var colH:Number;
			var colW:Number;
			
			// scratch vars
			var insetHeight:Number;
			
			// TODO: USE DIRECTION!!!
			if (_blockProgression == BlockProgression.TB)
			{
				if (_columnDirection == Direction.LTR)
				{
					xPos = _paddingLeft;
					delX = _columnWidth + _columnGap;
					colW = _columnWidth;
				}
				else
				{
					CONFIG::debug { assert(_columnDirection == Direction.RTL,"bad columndirection in ColumnState.computeColumns"); }
					xPos = isNaN(_compositionWidth) ? _paddingLeft : _compositionWidth-_paddingRight-_columnWidth;
					delX = -(_columnWidth + _columnGap);
					colW = _columnWidth;
				}
				yPos = _paddingTop;
				delY = 0;
				insetHeight = _paddingTop + _paddingBottom;
				colH = (_compositionHeight > insetHeight && !isNaN(_compositionHeight)) ? (_compositionHeight - insetHeight) : 0;
			}
			else if (_blockProgression == BlockProgression.RL)
			{
				xPos = isNaN(_compositionWidth) ? -_paddingRight : _paddingLeft -_compositionWidth;
				yPos = _paddingTop;
				delX = 0;
				delY = _columnWidth + _columnGap;
				insetHeight = _paddingLeft + _paddingRight;
				colW = (_compositionWidth > insetHeight) ? (_compositionWidth - insetHeight) : 0;
				colH = _columnWidth;
			}
			
			// make colW and colH just off zero so that we don't get empties
			if (colW == 0)
			{
				colW = Twips.ONE_TWIP;	// MINIMUM VALUE OF ONE TWIP
				if (_blockProgression == BlockProgression.RL)
					xPos -= colW;
			}
			if (colH == 0)
				colH = Twips.ONE_TWIP;	// MINIMUM VALUE OF ONE TWIP
			
			if (_columnCount == 1)
			{
				_singleColumn = new Rectangle(xPos, yPos, colW, colH);
				_columnArray = null;
			}
			else if (_columnCount == 0)
			{
				_singleColumn = null;
				_columnArray = null;
			}
			else
			{
				if (_columnArray)
					_columnArray.splice(0);
				else
					_columnArray = new Array();
				for (var i:int = 0; i < _columnCount; ++i)
				{
					_columnArray.push(new Rectangle(xPos, yPos, colW, colH));
					xPos += delX;
					yPos += delY;
				}
			}	
		}
	}
		

} // end package
