////////////////////////////////////////////////////////////////////////////////
//
//  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.operations
{
	import flashx.textLayout.edit.SelectionState;
	import flashx.textLayout.tlf_internal;
	import flashx.textLayout.elements.TextFlow;
	import flashx.textLayout.debug.assert;

	use namespace tlf_internal;

	/**
	 * The CompositeOperation class encapsulates a group of transformations managed as a unit.
	 *
	 * <p>The CompositeOperation class provides a grouping mechanism for combining multiple FlowOperations 
	 * into a single atomic operation. Grouping operations allows them to be undone and redone as a unit. 
	 * For example, several single character inserts followed by several backspaces can be undone together as if 
	 * they were a single operation. Grouping also provides a mechanism for representing
	 * complex operations. For example, a replace operation that modifies more than one text ranges
	 * can be represented and managed as a single composite operation.</p>
	 * 
	 * <p><b>Note:</b> It can be more efficient to merge individual atomic operations
	 *  rather than to combine separate operations into a group. For example, several sequential
	 *  character inserts can easily be represented as a single insert operation,
	 *  and undoing or redoing that single operation is more efficient than
	 *  undoing or redoing a group of insert operations.</p>
	 * 
	 * @see flashx.textLayout.edit.EditManager
	 * @see flashx.textLayout.events.FlowOperationEvent
	 * 
	 * @playerversion Flash 10
	 * @playerversion AIR 1.5
	 * @langversion 3.0 
	 */
	public class CompositeOperation extends FlowOperation
	{
		private var _operations:Array;
		
		/** 
		 * Creates a CompositeOperation object.
		 * 
		 * @param operations The operations to group.
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
	 	 * @langversion 3.0 
		 */
		public function CompositeOperation(operations:Array = null)
		{
			super(null);
			this.operations = operations;
		}

		/** @private */
		override public function get textFlow():TextFlow
		{ return _operations.length > 0 ? _operations[0].textFlow : null; }
		
		/**
		 * An array containing the operations grouped by this composite operation.
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
	 	 * @langversion 3.0 
		 */
		public function get operations():Array
		{
			return _operations;
		}
		public function set operations(value:Array):void
		{
			_operations = value ? value.slice() : [];	// make a copy
		}
		
		/** 
		 * Adds an additional operation to the end of the list. 
		 * 
		 * <p>The new operation must operate on the same TextFlow object as 
		 * the other operations in the list.</p>
		 * 
		 * @playerversion Flash 10
		 * @playerversion AIR 1.5
	 	 * @langversion 3.0 
		 */
		public function addOperation(operation:FlowOperation):void
		{
			// Can't handle operations from other TextFlows
			if (_operations.length > 0 && operation.textFlow != textFlow)
				return;
				
			CONFIG::debug { assert(_operations.length <= 0 || operation.beginGeneration == _operations[_operations.length - 1].endGeneration,
				"adding non-contiguous operation to composite operation"); }
			_operations.push(operation);
		}
		
		/** @private */
		public override function doOperation():Boolean
		{
			// execute all the operations in order
			var success:Boolean = true;
			for (var i:int = 0; i < _operations.length; i++)
				success = success && FlowOperation(_operations[i]).doOperation();
			
			// return selectionState from last operation
			return true;
		}
		
		/** @private */
		public override function undo():SelectionState
		{
			// undo all the operations in reverse order
			var selState:SelectionState;
			for (var i:int = _operations.length - 1; i >= 0; i--)
				selState = FlowOperation(_operations[i]).undo();
			
			// return selectionState from last performed
			// (i.e., the first in the set of operations)
			return selState;
		}
		
		/** @private */
		public override function redo():SelectionState
		{
			// execute all the operations in order
			var selState:SelectionState;
			for (var i:int = 0; i < _operations.length; i++)
				selState = FlowOperation(_operations[i]).redo();
			
			// return selectionState from last operation
			return selState;
		}		
		
		/** @private */
		public override function canUndo():Boolean
		{ 
			// All operations within the CompositeOperation must have matching generation numbers, and be undoable
			var undoable:Boolean = true;
			var generation:int = beginGeneration;
			var opCount:int = _operations.length;
			for (var i:int = 0; i < opCount && undoable; i++)
			{
				var op:FlowOperation = _operations[i];
				if (op.beginGeneration != generation || !op.canUndo())
					undoable = false;
				generation = op.endGeneration;
			}
			if (opCount > 0 && _operations[opCount - 1].endGeneration != endGeneration)
				undoable = false;
			
			return undoable; 
		}
		
		
		/** @private */
		tlf_internal override function merge(operation:FlowOperation):FlowOperation
		{
			if (operation is InsertTextOperation || operation is SplitParagraphOperation || operation is DeleteTextOperation)
			{
				if (this.endGeneration != operation.beginGeneration)
					return null;
				// For efficiency, try to combine the last low-level operation
				// with the new operation. If that's not possible, we just add it 
				// as an additional operation.
				// Note that we are making various assumptions here about the technical
				// feasability and appropriateness of merging the individual operations (e.g.,
				// that the selection hasn't changed), relying on SelectionManager to
				// guarantee that these are satisfied.
				var mergedOp:FlowOperation;
				var lastOp:FlowOperation = (_operations && _operations.length) ? 
										FlowOperation(_operations[_operations.length - 1]) :
										null;
				if (lastOp) 
					mergedOp = lastOp.merge(operation);
				
				if (mergedOp && !(mergedOp is CompositeOperation))
					_operations[_operations.length - 1] = mergedOp;
				else
					_operations.push(operation);
				return this;
			}
			return null;
		}
		
//		/**
//		 *  Add an additional operation to the end of this operation.
//		 *  If the additional operation is itself a CompositeOperation, 
//		 *  its child operations are just added to this operation's 
//		 *  set of child operations.
//		 * 	
//		 * @param operation The operation to be merged.
//		 * 
//		 */
//		private function mergeOperationViaConcatenation(operation:FlowOperation):void
//		{
//			var compositeOp:CompositeOperation = operation as CompositeOperation;
//			if (compositeOp)
//				operations = operations.concat(compositeOp.operations);
//			else
//				operations.push(operation);
//		}

	}
}