////////////////////////////////////////////////////////////////////////////////
//
//  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.edit
{
	import flash.utils.getQualifiedClassName;
	
	import flashx.textLayout.conversion.ConverterBase;
	import flashx.textLayout.debug.assert;
	import flashx.textLayout.elements.ContainerFormattedElement;
	import flashx.textLayout.elements.DivElement;
	import flashx.textLayout.elements.FlowElement;
	import flashx.textLayout.elements.FlowGroupElement;
	import flashx.textLayout.elements.FlowLeafElement;
	import flashx.textLayout.elements.LinkElement;
	import flashx.textLayout.elements.ListItemElement;
	import flashx.textLayout.elements.ParagraphElement;
	import flashx.textLayout.elements.SpanElement;
	import flashx.textLayout.elements.SubParagraphGroupElementBase;
	import flashx.textLayout.elements.TCYElement;
	import flashx.textLayout.elements.TextFlow;
	import flashx.textLayout.formats.ITextLayoutFormat;
	import flashx.textLayout.formats.TextLayoutFormat;
	import flashx.textLayout.tlf_internal;

	use namespace tlf_internal;
	
	[ExcludeClass]
	/**
	 * Encapsulates all methods necessary for dynamic editing of a text.  The methods are all static member functions of this class.
     * @private - because we can't make it tlf_internal. Used by the operations package 
	 */	
	public class TextFlowEdit
	{
		tlf_internal static function deleteRange(textFlow:TextFlow, startPos:int, endPos:int):ParagraphElement
		{
			var mergePara:ParagraphElement;

			// If the range to be deleted contains the paragraph end, we may have to merge up the paragraphs when we're done.
			if (endPos > startPos)
			{
				var firstLeafInRange:FlowLeafElement = textFlow.findLeaf(startPos);
				var lastLeafInRange:FlowLeafElement = textFlow.findLeaf(endPos - 1);
				var firstParagraphInRange:ParagraphElement = firstLeafInRange.getParagraph();
				var lastParagraphInRange:ParagraphElement = lastLeafInRange.getParagraph();
				var firstParaStart:int = firstParagraphInRange.getAbsoluteStart();
				var lastParaEnd:int = lastParagraphInRange.getAbsoluteStart() + lastParagraphInRange.textLength;
				// If the selection is inside a single paragraph, merge only if the terminator is included and the start of the paragraph is not.
				// If the two paragraphs are different, merge unless the start and end match exactly
				// Don't merge if the paragraph is an empty paragraph in a list item that has other content (it will just come back again in normalize)
				var doMerge:Boolean = false;
				if (firstParagraphInRange == lastParagraphInRange)
					doMerge = (endPos == lastParaEnd && startPos != firstParaStart);
				else
					doMerge = (startPos != firstParaStart);
				if (doMerge)
				{
					var followingLeaf:FlowLeafElement = textFlow.findLeaf(endPos);
					if (followingLeaf)
					{
						mergePara = followingLeaf.getParagraph();
						if (mergePara.textLength == 1 && mergePara.parent is ListItemElement && mergePara.parent.numChildren > 1)
							mergePara = null;
					}
				}
			}

			deleteRangeInternal(textFlow, startPos, endPos - startPos);
	
			if (mergePara)
			{
				var previousLeaf:FlowLeafElement = mergePara.getFirstLeaf().getPreviousLeaf();
				mergePara = previousLeaf ? previousLeaf.getParagraph() : null;
			}
			
			return mergePara;
		}
		
		private static function deleteRangeInternal(element:FlowGroupElement, relativeStart:int, numToDelete:int):void
		{
			var pendingDeleteStart:int = -1;
			var pendingDeleteCount:int = 0;
			
			var childIndex:int = element.findChildIndexAtPosition(relativeStart);
			while (numToDelete > 0 && childIndex < element.numChildren)
			{
				var child:FlowElement = element.getChildAt(childIndex);
				if (relativeStart <= child.parentRelativeStart && numToDelete >= child.textLength)	// remove the entire child
				{
					if (pendingDeleteStart < 0)
						pendingDeleteStart = childIndex;
					pendingDeleteCount++;
					numToDelete -= child.textLength;
				}
				else // deleting part of the child
				{
					if (pendingDeleteStart >= 0)
					{
						element.replaceChildren(pendingDeleteStart, pendingDeleteStart + pendingDeleteCount);
						childIndex -= pendingDeleteCount;
						pendingDeleteStart = -1;
						pendingDeleteCount = 0;
					}
					var childStart:int = child.parentRelativeStart;
					var childRelativeStart:int = Math.max(relativeStart - childStart, 0);
					var childNumToDelete:int = Math.min(child.textLength - childRelativeStart, numToDelete);
					if (child is SpanElement)
					{
						var span:SpanElement = child as SpanElement;
						span.replaceText(childRelativeStart, childRelativeStart + childNumToDelete, "");
						numToDelete -= childNumToDelete;
					}
					else
					{
						CONFIG::debug { assert (child is FlowGroupElement, "Expected FlowGroupElement"); }
						deleteRangeInternal(child as FlowGroupElement, childRelativeStart, childNumToDelete);
						numToDelete -= childNumToDelete;
					}
				}
				childIndex++
			}
			if (pendingDeleteStart >= 0)
				element.replaceChildren(pendingDeleteStart, pendingDeleteStart + pendingDeleteCount);
		}
				
		// Find the lowest possible FlowElement ancestor of element that can accept prospectiveChild as a child element.
		private static function findLowestPossibleParent(element:FlowGroupElement, prospectiveChild:FlowElement):FlowGroupElement
		{
			while (element && !element.canOwnFlowElement(prospectiveChild))
				element = element.parent;
			return element;
		}
		
		private static function removePasteAttributes(element:FlowElement):void
		{
			if (!element)
				return;
			
			if (element is FlowGroupElement && element.format)
			{
				var flowGroupElement:FlowGroupElement = FlowGroupElement(element);
				if (element.format.getStyle(ConverterBase.MERGE_TO_NEXT_ON_PASTE) !== undefined)
					removePasteAttributes(flowGroupElement.getChildAt(flowGroupElement.numChildren - 1));
			}
			element.setStyle(ConverterBase.MERGE_TO_NEXT_ON_PASTE, undefined);		
		}
		
		// Apply the formatting attributes from the (soon to be) previous element to the insertThis element(s). Used when we're about to 
		// insert the element(s) and we want it to adopt the formatting of its context.
		private static function applyFormatToElement(destinationElement:FlowGroupElement, childIndex:int, insertThis:Object):void
		{
			var formatSourceSibling:FlowElement;
			
			// find the previous sibling and use its formats for the new siblings
			if (childIndex > 0)
				formatSourceSibling = destinationElement.getChildAt(childIndex - 1);
			else
				formatSourceSibling = destinationElement.getChildAt(0);
			if (formatSourceSibling)
			{ 
				var spanFormat:ITextLayoutFormat;
				if (formatSourceSibling is FlowGroupElement)	// take all levels from the sibling down to the root into account
				{
					var element:FlowElement = FlowGroupElement(formatSourceSibling).getLastLeaf();
					var concatFormat:TextLayoutFormat;
					while (element != formatSourceSibling.parent)
					{
						if (element.format)
						{
							if (!concatFormat)
								concatFormat = new TextLayoutFormat(element.format);
							else 
								concatFormat.concatInheritOnly(element.format);
						}
						element = element.parent;
					}
					spanFormat = concatFormat;
				}
				else 
					spanFormat = formatSourceSibling.format;
					
				if (insertThis is Array)
				{
					for each (var scrapElement:FlowElement in insertThis)
						if (scrapElement is FlowLeafElement)
							scrapElement.format = spanFormat;
						else
							scrapElement.format = formatSourceSibling.format;
				}
				else if (insertThis is FlowLeafElement)
					insertThis.format = spanFormat;
				else
					insertThis.format = formatSourceSibling.format;
			}
		}
		/**
		 * Replaces the range of text positions that the <code>startPos</code> and
		 * <code>endPos</code> parameters specify with the <code>textScrap</code> parameter in
		 * <code>theFlow</code>.
		 * <p>To delete elements, pass <code>null</code> for <code>newTextFlow</code>.</p>
		 * <p>To insert an element, pass the same value for <code>startPos</code> and <code>endPos</code>.
		 * <p>The new element will be inserted before the specified index.</p>
		 * <p>To append the TextFlow, pass <code>theFlow.length</code> for <code>startPos</code> and <code>endPos</code>.</p>
		 * 
		 * @param textFlow The TextFlow that is being inserted into.
		 * @param absoluteStart The index value of the first position of the replacement range in the TextFlow.
		 * @param textScrap The TextScrap to be pasted into theFlow.
		 */				
		public static function insertTextScrap(textFlow:TextFlow, absoluteStart:int, textScrap:TextScrap, applyFormat:Boolean):int
		{
			if (!textScrap)
				return absoluteStart;
			
			var scrapFlow:TextFlow = textScrap.textFlow.deepCopy() as TextFlow;
			var scrapLeaf:FlowLeafElement = scrapFlow.getFirstLeaf();

			var destinationLeaf:FlowLeafElement = textFlow.findLeaf(absoluteStart);		
			var insertPosition:int = absoluteStart;
			
			var firstParagraph:Boolean = true;
			var doSplit:Boolean = false;
			
			while (scrapLeaf)
			{
				removePasteAttributes(scrapLeaf);
				var scrapElement:FlowElement = scrapLeaf;		// highest level complete element in the scrap

				// On the first paragraph, it always merges in to the destination paragraph if the destination paragraph has content
				var destinationParagraph:ParagraphElement = destinationLeaf.getParagraph();
				if (firstParagraph && (destinationParagraph.textLength > 1 || applyFormat))
				{
					var scrapParagraph:ParagraphElement = scrapLeaf.getParagraph();
					if (!scrapParagraph.format || scrapParagraph.format.getStyle(ConverterBase.MERGE_TO_NEXT_ON_PASTE) === undefined)
						doSplit = true;
					scrapElement = scrapParagraph.getChildAt(0);
				}
				else
				{
					if (applyFormat && firstParagraph)
					{
						destinationElement = findLowestPossibleParent(destinationLeaf.parent, scrapElement);
						var currentIndex:int = destinationElement.findChildIndexAtPosition(insertPosition - destinationElement.getAbsoluteStart());
						applyFormatToElement(destinationElement, currentIndex, scrapElement);
					}
					// Normally the root element of the scrap is marked as partial, but if not, just assume that its partial (we never paste the TextFlow element)
					while (scrapElement && scrapElement.parent && (!scrapElement.parent.format || scrapElement.parent.format.getStyle(ConverterBase.MERGE_TO_NEXT_ON_PASTE) === undefined) && !(scrapElement.parent is TextFlow))
						scrapElement = scrapElement.parent;
				}
				

				// Find the lowest level parent in the TextFlow that can accept the scrapElement as a child. 
				// If necessary, copy higher up the scrapElement hierarchy to find a match.
				var destinationElement:FlowGroupElement = findLowestPossibleParent(destinationLeaf.parent, scrapElement);
				while (!destinationElement)
				{
					// Nothing in the TextFlow element hierarchy can accept the incoming scrap element.
					// Go up the scrapElement's hierarchy of partial nodes until we find one that can be inserted.
					scrapElement = scrapElement.parent;
					CONFIG::debug { assert(scrapElement != null, "Couldn't find scrapElement that could be pasted"); }
					destinationElement = findLowestPossibleParent(destinationLeaf.parent, scrapElement);
				}
				CONFIG::debug { assert(destinationElement != null, "insertTextScrap failed to find a FlowElement that can take the scrap element"); }
				
				removePasteAttributes(scrapElement);

				var destinationStart:int = destinationElement.getAbsoluteStart();
				if (firstParagraph && doSplit)
				{
					// Split the paragraph, and merge the scrap paragraph to the end of the first paragraph of the destination
					CONFIG::debug { assert(destinationElement is ParagraphElement, "We should be splitting a paragraph"); }
					ModelEdit.splitElement(textFlow, destinationElement, insertPosition - destinationStart);
					var scrapParent:FlowGroupElement = scrapElement.parent;
					var scrapChildren:Array = scrapParent.mxmlChildren;
					scrapParent.replaceChildren(0, scrapParent.numChildren);
					if (scrapParent.parent)
						scrapParent.parent.removeChild(scrapParent);
					if (applyFormat)
						applyFormatToElement(destinationElement, destinationElement.numChildren, scrapChildren);
					destinationElement.replaceChildren(destinationElement.numChildren, destinationElement.numChildren, scrapChildren);
					scrapElement = destinationElement.getChildAt(destinationElement.numChildren - 1);		// last span pasted, so we'll paste next after this
					firstParagraph = false;
				}
				else
				{
					// We're going to add scrapElement as a child of destinationElement at the insertPosition.
					// Split the children of destinationElement if necessary.
					var childIndex:int = destinationElement.findChildIndexAtPosition(insertPosition - destinationElement.getAbsoluteStart());
					var child:FlowElement = destinationElement.getChildAt(childIndex);
					var childStart:int = child.getAbsoluteStart();
					if (insertPosition == childStart + child.textLength)
						++childIndex;
					else if (insertPosition > childStart)
					{
						if (child is FlowLeafElement)
							child.splitAtPosition(insertPosition - childStart);
						else
							ModelEdit.splitElement(textFlow, child as FlowGroupElement, insertPosition - childStart);
						++childIndex;
					}
					if (applyFormat)
						applyFormatToElement(destinationElement, childIndex, scrapElement);
					destinationElement.replaceChildren(childIndex, childIndex, scrapElement);
				}

				
				// Advance to the next destination leaf
				destinationLeaf = (scrapElement is FlowLeafElement) ? FlowLeafElement(scrapElement).getNextLeaf() : FlowGroupElement(scrapElement).getLastLeaf().getNextLeaf();
				insertPosition = destinationLeaf ? destinationLeaf.getAbsoluteStart() : textFlow.textLength - 1;
				
				scrapLeaf = scrapFlow.getFirstLeaf();
			}
			
			return insertPosition;
		}

		/**
		 * Creates a TCY run out of the selected positions.
		 * @param theFlow The TextFlow of interest.
		 * @param startPos The index value of the first position of the TextFlow to be turned into a TCY run.
		 * @param endPos The index value following the end position of the TextFlow to be turned into a TCY run.
		 */	
		public static function makeTCY(theFlow:TextFlow, startPos:int, endPos:int):Boolean
		{
			var madeTCY:Boolean = true;
			var curPara:ParagraphElement = theFlow.findAbsoluteParagraph(startPos);
			if(!curPara)
				return false;
			while(curPara)
			{
				var paraEnd:int = curPara.getAbsoluteStart() + curPara.textLength;
				var curEndPos:int = Math.min(paraEnd, endPos);
				
				//we have an entire para selected and the para only contains a kParaTerminator char, which cannot be
				//made into TCY. 
				if(canInsertSPBlock(theFlow, startPos, curEndPos, TCYElement) && curPara.textLength > 1)
				{
					var new_tcyElem:TCYElement = new TCYElement();
					
					//don't hide an error!
					madeTCY = madeTCY && insertNewSPBlock(theFlow, startPos, curEndPos, new_tcyElem, TCYElement);
				}
				else
					madeTCY = false;
				
				if(paraEnd < endPos)
				{
					curPara = theFlow.findAbsoluteParagraph(curEndPos);	
					startPos = curEndPos;
				}
				else
					curPara = null;
			}
			
			return madeTCY;
		}
		
		/**
		 * Creates one or more LinkElements out of the selected positions. It will go through
		 * every paragraph within the selected position and make links.
		 * @param theFlow The TextFlow of interest.
		 * @param startPos The index value of the first position of the TextFlow to be turned into a link.
		 * @param endPos The index value following the end position of the TextFlow to be turned into a link.
		 * @param urlString The url string to be associated with the link.
		 */			
		public static function makeLink(theFlow:TextFlow, startPos:int, endPos:int, urlString:String, target:String):Boolean
		{
			var madeLink:Boolean = true;
			var curPara:ParagraphElement = theFlow.findAbsoluteParagraph(startPos);
			if(!curPara)
				return false;
				
			while(curPara)
			{
				var paraEnd:int = curPara.getAbsoluteStart() + curPara.textLength;
				var curEndPos:int = Math.min(paraEnd, endPos);
				var linkEndPos:int = (curEndPos == paraEnd) ? (curEndPos - 1) : curEndPos;
				if (linkEndPos > startPos)
				{
					//if the end of the paragraph is < endPos, we are going across bounds
					if(!canInsertSPBlock(theFlow, startPos, linkEndPos, LinkElement))
					{
						return false;
					}
				
					var newLinkElement:LinkElement = new LinkElement();
					newLinkElement.href = urlString;
					newLinkElement.target = target;
				
					//don't hide an error!
					madeLink = madeLink && insertNewSPBlock(theFlow, startPos, linkEndPos, newLinkElement, LinkElement);
				}	
				if(paraEnd < endPos)
				{
					curPara = theFlow.findAbsoluteParagraph(curEndPos);	
					startPos = curEndPos;
				}
				else
					curPara = null;
			}
			
			return madeLink;
		}
		
		
		/**
		 * Removes the TCY block at the selected positions. 
		 * @param theFlow The TextFlow of interest.
		 * @param startPos The index value of the first position of the TextFlow.
		 * @param endPos The index value following the end position of the TextFlow.
		 */			
		public static function removeTCY(theFlow:TextFlow, startPos:int, endPos:int):Boolean
		{
			if (endPos <= startPos)
			{
				return false;
			}
			
			return findAndRemoveFlowGroupElement(theFlow, startPos, endPos, TCYElement);
		}
		
		/**
		 * Removes all LinkElements under the selected positions. It will go through
		 * every paragraph within the selected position and remove any link.
		 * @param theFlow The TextFlow of interest.
		 * @param startPos The index value of the first position of the TextFlow.
		 * @param endPos The index value following the end position of the TextFlow.
		 */			
		public static function removeLink(theFlow:TextFlow, startPos:int, endPos:int):Boolean
		{
			if (endPos <= startPos)
			{
				return false;
			}
			
			return findAndRemoveFlowGroupElement(theFlow, startPos, endPos, LinkElement);
		}
		
		/**
		 * @private
		 * insertNewSPBlock - add a SubParagraphGroupElementBase (spg) to <code>theFlow</code> at the indicies specified by <code>startPos</code> and
		 * <code>endPos</code>.  The <code>newSPB</code> will take ownership of any FlowElements within the range and will split them
		 * as needed.  If the parent of the FlowGroupElement indicated by <code>startPos</code> is the same as <code>spgClass</code> then
		 * the method fails and returns false because a spg cannot own children of the same class as itself.  Any spg of type <code>spgClass</code>
		 * found within the indicies, however, is subsumed into <code>newSPB</code>, effectively replacing it.
		 *
		 * @param theFlow:TextFlow - The TextFlow that is the destination for the newSPB
		 * @param startPos:int - The absolute index value of the first position of the range in the TextFlow to perform the insertion.
		 * @param endPos:int - The index value following the end position of the range in the TextFlow to perform the insertion.
		 * @param newSPB:SubParagraphGroupElementBase - The new SubParagraphElement which is to be added into theFlow.
		 * @param spgClass:Class - the class of the fbe we intend to add.
		 * 
		 * Examples: Simple and complex where insertion is of <code>spgClass</code> b.  Selection is l~o
		 *		1) <a><span>ghijklmnop</span></a>
		 * 		2) <a><span>ghij</span><b><span>klm</span></b><span>nop</span></a>
		 * 		3) <a><span>ghijk</span><c><span>lmn</span></c><span>op</span></a>
		 * 
		 */
		tlf_internal static function insertNewSPBlock(theFlow:TextFlow, startPos:int, endPos:int, newSPB:SubParagraphGroupElementBase, spgClass:Class):Boolean
		{
			var curPos:int = startPos;
			var curFBE:FlowGroupElement = theFlow.findAbsoluteFlowGroupElement(curPos);
			var elementIdx:int = 0;
			
			CONFIG::debug{ assert(curFBE != null, "No FBE at location curPos(" + curPos + ")!");}
			
			//if we are at the last "real" glyph of the paragraph, include the terminator.
			var paraEl:ParagraphElement = curFBE.getParagraph();
			if(endPos == (paraEl.getAbsoluteStart() + paraEl.textLength - 1))
				++endPos;
			
			//before processing this any further, we need to make sure that we are not
			//splitting a spg which is contained within the same type of spg as the curFBE's parent.
			//for example, if we had a tcyElement inside a linkElement, then we cannot allow a link element
			//to be made within the tcyElement as the link would not function.  As a rule, a SubParagraphElement
			//cannot own a child of the same class.
			//
			//However, if the curFBE is parented by a spg and the objects have the same start and end, then we are doing
			//a replace and we're not splitting the parent. Check if the bounds are the same and if so, don't skip it...
			var parentStart:int = curFBE.parent.getAbsoluteStart();
			var curFBEStart:int = curFBE.getAbsoluteStart();
			if(curFBE.parent && curFBE.parent is spgClass && 
				!(parentStart == curFBEStart && parentStart + curFBE.parent.textLength == curFBEStart + curFBE.textLength))
			{
				return false;
			}
			
			//entire FBE is selected and is not a paragraph, get its parent.
			if(!(curFBE is ParagraphElement) && curPos == curFBEStart && curPos + curFBE.textLength <= endPos)
			{
				elementIdx = curFBE.parent.getChildIndex(curFBE);
				curFBE = curFBE.parent;
			}
			//first, if the curFBE is of the same class as the newSPB, then we need to split it to allow for insertion
			//of the new one IF the start position is > the start of the curFBE
			//
			//running example after this block:
			//	1) <a><span>ghijk</span><span>lmnop</span></a>
			//	2) <a><span>ghij</span><b><span>k</span></b><b><span>lm</span></b><span>nop</span></a>
			//	3) <a><span>ghijk</span><c><span>lmn</span></c><span>op</span></a> - no change
			if(curPos >= curFBEStart)
			{
				if(!(curFBE is spgClass))
					elementIdx = findAndSplitElement(curFBE, elementIdx, curPos, true);
				else
				{
					elementIdx = findAndSplitElement(curFBE.parent, curFBE.parent.getChildIndex(curFBE), curPos, false);
					curFBE = curFBE.parent;
				}
			}
			
			//now that the curFBE has been split, we want to insert the newSPB into the flow and then start absorbing the
			//contents...
			//running example after this block:
			//	1) <a><span>ghijk</span><b></b><span>lmnop</span></a>
			//	2) <a><span>ghij</span><b><span>k</span></b><b></b><b><span>lm</span></b><span>nop</span></a>
			//	3) <a><span>ghijk</span><b></b><c><span>lmn</span></c><span>op</span></a> - no change
			//
		//	we need another use case here where selection is entire sbp and selection runs from the head of a spg to
		//	part way through it - so that a) does into parent and b) goes into spg
			
			// if this is case 2, then the new element must go into the parent...
			if(curFBE is spgClass)
			{
				curFBEStart = curFBE.getAbsoluteStart();
				elementIdx = curFBE.parent.getChildIndex(curFBE);
				if(curPos > curFBEStart)//we're splitting the element, not replacing it...
					elementIdx += 1;
				
				//if the spg, curFBE is entirely selected then we want to use the parent, not the item itself.
				while(endPos >= curFBEStart + curFBE.textLength)
				{
					//we need access to the parent, which contains both the start and end not the FBE we just split
					curFBE = curFBE.parent;
				}
				curFBE.replaceChildren(elementIdx, elementIdx, newSPB);
			}
			else
			{
				//we're inserting into the curFBE
				curFBE.replaceChildren(elementIdx, elementIdx, newSPB);
			}
			
			//see subsumeElementsToSPBlock to see effects on running example
			subsumeElementsToSPBlock(curFBE, elementIdx + 1, curPos, endPos, newSPB, spgClass);
			
			return true;
		}
		
		
		/**
		 * @private
		 * splitElement - split <code>elem</code> at the relative index of <code>splitPos</code>.  If <code>splitSubBlockContents</code>
		 * is true, split the contents of <code>elem</code> if it is a SubParagraphGroupElementBase, otherwise just split <code>elem</code>
		 * 
		 * @param elem:FlowElement - the FlowElement to split
		 * @param splitPos:int - The elem relative index indicating where to split
		 * @param splitSubBlockContents:Boolean - boolean indicating whether a SubParagraphGroupElementBase is to be split OR that it's contents
		 * should be split.  For example, are we splitting a link or are we splitting the child of the link
		 * 
		 * <spg><span>ABCDEF</span></spg>
		 * 
		 * if <code>splitPos</code> indicated index between C and D, then if <code>splitSubBlockContents</code> equals true,
		 * result is:
		 * 
		 * <spg><span>ABC</span><span>DEF</span></spg>
		 * 
		 * if <code>splitSubBlockContents</code> equals false, result is:
		 * 
		 * <spg><span>ABC</span></spg><spg><span>DEF</span></spg>
		 */
		tlf_internal static function splitElement(elem:FlowElement, splitPos:int, splitSubBlockContents:Boolean):void
		{
			CONFIG::debug{ assert(splitPos < elem.textLength, "trying to splic FlowElement at illegal index!"); }
			if (elem is SpanElement)
			{
				SpanElement(elem).splitAtPosition(splitPos);
			}
			else if(elem is SubParagraphGroupElementBase && splitSubBlockContents)
			{
				var subBlock:SubParagraphGroupElementBase = SubParagraphGroupElementBase(elem);
				// Split the SpanElement of the block at splitPos.  If the item at the splitPos is not a SpanElement, no action occurs.
				var tempElem:SpanElement = subBlock.findLeaf(splitPos) as SpanElement;
				if (tempElem)
					tempElem.splitAtPosition(splitPos - tempElem.getElementRelativeStart(subBlock));
			}
			else if (elem is FlowGroupElement)
			{
				FlowGroupElement(elem).splitAtPosition(splitPos);
			}
			else
			{
				CONFIG::debug { assert(false, "Trying to split on an illegal FlowElement"); }				
			}
		}
		
		/**
		 * @private
		 * findAndSplitElement - starting at the child <code>elementIdx</code> of <code>fbe</code>, iterate
		 * through the elements untill we find the one located at the aboslute index of <code>startIdx</code>. Upon
		 * locating the child, split either the element itself OR its children based on the value of <code>splitSubBlockContents</code>
		 * 
		 * @param fbe:FlowGroupElement - the FBE into which the newSPB is being inserted.
		 * @param elementIdx:int - The index into the <code>fbe's</code> child list to start
		 * @param startIdx:int - The absolute index value into the TextFlow.
		 * @param splitSubBlockContents:Boolean - boolean indicating whether a subElement is to be split OR that it's contents
		 * should be split.  For example, are we splitting a link or are we splitting the child of the link
		 * 
		 * <p>ZYX<link>ABCDEF</link>123</p>
		 * 
		 * if we are inserting a TCY into the link, splitSubBlockContents should be false. We want to split the span ABCDEF such that result is:
		 * <p>ZYX<link>AB<tcy>CD</tcy>EF</link>123</p>
		 * 
		 * if we are creating a new link from X to B, then we want the link to split and splitSubBlockContents should be false:
		 * 
		 * <p>ZY<link>XAB</link><link>CDEF</link>123</p>
		 * 
		 * @return int - the index of the last child of <code>fbe</code> processed.
		 */
		tlf_internal static function findAndSplitElement(fbe:FlowGroupElement, elementIdx:int, startIdx:int, splitSubBlockContents:Boolean):int
		{
			var curFlowEl:FlowElement = null;
			var curIndexInPar:int = startIdx - fbe.getAbsoluteStart();
			
			while(elementIdx < fbe.numChildren)
			{
				curFlowEl = fbe.getChildAt(elementIdx);
				if (curIndexInPar == curFlowEl.parentRelativeStart)
					return elementIdx;
				if ((curIndexInPar > curFlowEl.parentRelativeStart) && (curIndexInPar < curFlowEl.parentRelativeEnd))
				{
					splitElement(curFlowEl, curIndexInPar - curFlowEl.parentRelativeStart, splitSubBlockContents); 
				}
				++elementIdx;
			}
			return elementIdx;
		}
		
		/**
		 * @private
		 * subsumeElementsToSPBlock - incorporates all elements of <code>parentFBE</code> into
		 * the <code>newSPB</code> between the <code>curPos</code> and <code>endPos</code>.  If a child of
		 * <code>parentFBE</code> is of type <code>spgClass</code> then the child's contents are removed from the child,
		 * added to the <code>newSPB</code>, the child is then removed from the <code>parentFBE</code>
		 * 
		 * @param parentFBE:FlowGroupElement - the FBE into which the newSPB is being inserted.
		 * @param startPos:int - The index value of the first position of the replacement range in the TextFlow.
		 * @param endPos:int - The index value following the end position of the replacement range in the TextFlow.
		 * @param newSPB:SubParagraphGroupElementBase - the new SubParagraphGroupElementBase we intend to insert.
		 * @param spgClass:Class - the class of the fbe we intend to insert.
		 * 
		 * @return int - the aboslute index in the text flow after insertion.
		 * 
		 *  Examples: Simple and complex where insertion is of <code>spgClass</class> b.  Selection is l~o
		 *		1) <a><span>ghijk</span><b></b><span>lmnop</span></a>
		 *		2) <a><span>ghij</span><b><span>k</span></b><b></b><b><span>lm</span></b><span>nop</span></a>
		 * 
		 * 	parentFBE = <a>
		 *  elementIdx = 1) 2, 2) 3
		 *  curPos = 5
		 *  endPos = 9
		 *  newSPB is of type <b>
		 */
		tlf_internal static function subsumeElementsToSPBlock(parentFBE:FlowGroupElement, elementIdx:int, curPos:int, endPos:int, newSPB:SubParagraphGroupElementBase, spgClass:Class):int
		{
			var curFlowEl:FlowElement = null;
			
			//if we have an invalid index, then skip out.  elementIdx will always point one
			//element beyond the one we are inserting....
			if(elementIdx >= parentFBE.numChildren)
				return curPos;
			
			while (curPos < endPos)
			{
				//running example: curFlowEl is the element immediately after the inserted newSPB:
				//	1) <a><span>ghijk</span><b></b><span>lmnop</span></a>
				//		points to span-lmnop
				//	2) <a><span>ghij</span><b><span>k</span></b><b></b><b><span>lm</span></b><span>nop</span></a>
				//		points to b-lm
				curFlowEl = parentFBE.getChildAt(elementIdx);
				
				//if the curFlowEl is of the Class we are adding (spgClass), and the entire thing is selected,
				//then we are adding the entire block, but not spliting it - perform the split on the next block
				
				//I think this can be safely removed from here as ownership of contents is handled below.
				//leaving in commented out code in case we need to revert - gak 05.01.08
			/*	if(curFlowEl is spgClass && curPos == curFlowEl.getAbsoluteStart() && curFlowEl.getAbsoluteStart() + curFlowEl.textLength <= endPos)
				{
					curPos = parentFBE.getAbsoluteStart() + parentFBE.textLength;
					continue;
				}*/
				
				//if the endPos is less than the length of the curFlowEl, then we need to split it.
				//if the curFlowEl is NOT of class type spgClass, then we need to break it
				//
				//Use case: splitting a link in two (or three as will be the result with head and tail sharing
				//attributes...
				//running example 1 hits this, but 2 does not. Using variation of 2:
				//
				// example: 1) <a><span>ghijk</span><b></b><span>lmnop</span></a>
				// 			2a) <a><span>fo</span><b></b><b><span>obar</span></b></a> - selection: from o~a
				//
				// after this code:
				//			1) <a><span>ghijk</span><b></b><span>lmno</span><span>p</span></a>
				//			2a) <a><span>fo</span><b></b><b><span>oba</span></b><b><span>or</span></b></a>
				if ((curPos + curFlowEl.textLength) > endPos)
				{
					splitElement(curFlowEl, endPos - curFlowEl.getAbsoluteStart(), !(curFlowEl is spgClass));  //changed to curFlowEl from newSPB as newSPB should be of type spgClass
				}
				
				//add the length before replacing the elements
				curPos += curFlowEl.textLength;
				
				//running example: after parentFBE.replaceChildren
				//
				//	1) curFlowEl = <span>lmno</span>
				//		<a><span>ghijk</span><b></b>{curFlowEl}<span>p</span></a>
				//
				//	2) curFlowEl = <b><span>lm</span></b>
				//		<a><span>ghij</span><b><span>k</span></b><b></b>{curFlowEl}<span>nop</span></a>
				parentFBE.replaceChildren(elementIdx, elementIdx + 1);
				
				//if the curFlowEl is of type spgClass, then we need to take its children and
				//add them to the newSPB because a spg cannot contain a child of the same class
				//as itself
				//
				// exmaple: 2) curFlowEl = <b><span>lm</span></b>
				if (curFlowEl is spgClass)
				{
					var subBlock:SubParagraphGroupElementBase = curFlowEl as SubParagraphGroupElementBase;
					//elementCount == 1 - <span>lm</span>
					while (subBlock.numChildren > 0)
					{
						//fe[0] = <span>lm</span>
						var fe:FlowElement = subBlock.getChildAt(0);
						//<span></span>
						subBlock.replaceChildren(0, 1);
						//<b><span>lm</span></b>
						newSPB.replaceChildren(newSPB.numChildren, newSPB.numChildren, fe);
					}
					//when compelete, example 2 is:
					//2) <a><span>ghij</span><b><span>k</span></b><b><span>lm</span></b><span>nop</span></a>
				}
				else 
				{
					//example 1, curFlowEl is <span>lmno</span>, so this is not hit
					//
					// extending element <a> from foo~other
					// <a>foo</a><b>bar<a>other</a><b>
					// curFlowEl = <b>bar<a>other</a><b>
					//
					// since <b> is a spg, we need to walk it's contents and remove any <a> elements
					if(curFlowEl is SubParagraphGroupElementBase)
					{
						//we need to dive into this spgClass and remove any fbes of type spgClass
						//pass in the curFlowEl as the newSPB, remove any spgs of type spgClass, then 
						//perform the replace on the newSPB passed in here
						//
						//ignore the return value of the recursive call as the length has already been
						//accounted for above
						flushSPBlock(curFlowEl as SubParagraphGroupElementBase, spgClass);
					}
					newSPB.replaceChildren(newSPB.numChildren, newSPB.numChildren, curFlowEl);
					
					if(newSPB.numChildren == 1 && curFlowEl is SubParagraphGroupElementBase)
					{
						var childSPGE:SubParagraphGroupElementBase = curFlowEl as SubParagraphGroupElementBase;
						//running example:
						//a.precedence = 800, tcy.precedence = kMinSPGEPrecedence
						//this = <tcy><a><span>fooBar</span></a><tcy>
						//childSPGE = <a><span>fooBar</span></a>
						if(childSPGE.textLength == newSPB.textLength && (curPos >= endPos))
						{
							CONFIG::debug { assert(childSPGE.precedence != newSPB.precedence, "normalizeRange found two equal SPGEs"); }
	
							//if the child's precedence is higher than mine, I need to swap
							if(childSPGE.precedence > newSPB.precedence)
							{
								//first, remove the child
								//this = <tcy></tcy>
								newSPB.replaceChildren(0,1);
								
								//we need to flop this object for the child
								while(childSPGE.numChildren > 0)
								{
									//tempFE = <span>fooBar</span>
									var tempFE:FlowElement = childSPGE.getChildAt(0);
									//child = <a></a>
									childSPGE.replaceChildren(0,1);
									//this = <tcy><span>fooBar</span></tcy>
									newSPB.replaceChildren(newSPB.numChildren, newSPB.numChildren, tempFE);
								}
								
								var myIdx:int = newSPB.parent.getChildIndex(newSPB);
								CONFIG::debug{ assert(myIdx >= 0, "Invalid index!  How can a SubParagraphGroupElementBase normalizing not have a parent!"); }
								
								//add childSPGE in my place
								newSPB.parent.replaceChildren(myIdx, myIdx + 1, childSPGE)
								
								//childSPGE = <tcy><a><span>fooBar</span></a></tcy>
								childSPGE.replaceChildren(0,0,newSPB);
							}
						}
					}
				}
				
			}
	
			return curPos;
		}
		
		/**
		 * @private
		 * findAndRemoveFlowGroupElement 
		 *
		 * @param theFlow The TextFlow that is containing the elements to remove.
		 * @param startPos The index value of the first position of the range in the TextFlow where we want to perform removal.
		 * @param endPos The index value following the end position of the range in the TextFlow where we want to perform removal.
		 * @param fbeClass Class the class of the fbe we intend to remove.
		 * 
		 * Walks through the elements of <code>theFlow</code> looking for any FlowGroupElement of type <code>fbeClass</class>
		 * On finding one, it removes the FBE's contents and adds them back into the FBE's parent.  If the class of object is
		 * embedded within another spg and this removal would break the parent spg, then the method does nothing.
		 * 
		 * Example:
		 * 	<link>ABC<tcy>DEF</tcy>GHI</link>
		 * 	Selection is on E and removal of link is attempted.
		 * 	Because E is a child of a spg (tcy), and removing the link from E would split the parent spg (link),
		 *  the action is disallowed.
		 * 
		 * Running example:
		 * 	1) <link><tcy><span>foo</span></tcy><span>bar</span></link>
		 * @return Boolean - true if items are removed or none are found.  false if operation is illegal.
		 */ 
		tlf_internal static function findAndRemoveFlowGroupElement(theFlow:TextFlow, startPos:int, endPos:int, fbeClass:Class):Boolean
		{
			var curPos:int = startPos;
			var curEl:FlowElement;
			
			//walk through the elements
			while (curPos < endPos)
			{
				var containerFBE:FlowGroupElement = theFlow.findAbsoluteFlowGroupElement(curPos);
				
				//if the start of the parent is the same as the start of the current containerFBE, then
				//we potentially have the wrong object.  We need to walk up the parents until we get to
				//the one which starts at our start AND is the topmost object at that index.
				//example: <a><b>foo</b> bar</a> - getting the object at "f" will yield the <b> element, not <a>
				while(containerFBE.parent && containerFBE.parent.getAbsoluteStart() == containerFBE.getAbsoluteStart() && 
					!(containerFBE.parent is ParagraphElement) && !(containerFBE is ParagraphElement)) //don't go beyond paragraph
				{
					containerFBE = containerFBE.parent;
				}
				
				//if the absoluteFBE is the item we are trying to remove, we need to work with its parent, so
				//reassign containerFBE.  For example, if an entire link were selected, we'd need to get it's parent to
				//perform the removal
				if(containerFBE is fbeClass)
					containerFBE = containerFBE.parent;
					
				//before processing this any further, we need to make sure that we are not
				//splitting a spg which is contained within the same type of spg as the curFBE's parent.
				//for example, if we had a tcyElement inside a linkElement, then we cannot allow a link element
				//to be broken within the tcyElement as the link would have to split the TCY.
				var ancestorOfFBE:FlowGroupElement = containerFBE.parent;
				while(ancestorOfFBE != null && !(ancestorOfFBE is fbeClass))
				{
					if(ancestorOfFBE.parent is fbeClass)
					{
						return false;
					}
					ancestorOfFBE = ancestorOfFBE.parent;
				}
				
				//if this is a sbe block contained in another sbe, and it is entire within the 
				//selection bounds, we need to use the parent sbe's container.  If it is splitting
				//the child sbe, we don't allow this and it is handled later...
				var containerFBEStart:int = containerFBE.getAbsoluteStart();
				if(ancestorOfFBE is fbeClass && (containerFBEStart >= curPos && containerFBEStart + containerFBE.textLength <= endPos))
					containerFBE = ancestorOfFBE.parent;
					
				var childIdx:int = containerFBE.findChildIndexAtPosition(curPos - containerFBEStart);
				curEl = containerFBE.getChildAt(childIdx);
				if(curEl is fbeClass)
				{
					CONFIG::debug{ assert(curEl is SubParagraphGroupElementBase, "Wrong FBE type!  Trying to remove illeage FBE!"); }
					var curFBE:FlowGroupElement = curEl as FlowGroupElement;
					
					//get it's parent and the index of the curFBE
					var parentBlock:FlowGroupElement = curFBE.parent;
					var idxInParent:int = parentBlock.getChildIndex(curFBE);
					
					//if the curPos is not at the head of the SPB, then we need to split it here
					//curFBE will point to the FBE starting at curPos
					if(curPos > curFBE.getAbsoluteStart())
					{
						splitElement(curFBE, curPos - curFBE.getAbsoluteStart(), false);
						curPos = curFBE.getAbsoluteStart() + curFBE.textLength;
						continue;
					}
					
					//if curFBE goes beyond the endPos, then we need to split off the tail.
					if (curFBE.getAbsoluteStart() + curFBE.textLength > endPos)
					{
						splitElement(curFBE, endPos - curFBE.getAbsoluteStart(), false);
					}
				
					//apply the length of the curFBE to the curPos tracker.  Do this before 
					//removing the contents or it will be 0!
					curPos = curFBE.getAbsoluteStart() + curFBE.textLength;
					
					//walk all the contents of the FBE into it's parent container
					while (curFBE.numChildren > 0)
					{
						var childFE:FlowElement = curFBE.getChildAt(0);
						curFBE.replaceChildren(0, 1);
						parentBlock.replaceChildren(idxInParent, idxInParent, childFE);
						idxInParent++; 
					}
					
					//remove the curFBE
					parentBlock.replaceChildren(idxInParent, idxInParent + 1);
				}
				else if(curEl is SubParagraphGroupElementBase) //check all the parents...
				{
					var curSPB:SubParagraphGroupElementBase = SubParagraphGroupElementBase(curEl);
					if(curSPB.numChildren == 1)
						curPos = curSPB.getAbsoluteStart() + curSPB.textLength;
					else
					{
						curEl = curSPB.getChildAt(curSPB.findChildIndexAtPosition(curPos - curSPB.getAbsoluteStart()));
						curPos = curEl.getAbsoluteStart() + curEl.textLength;
					}
				}
				else
				{
					//the current block isn't the type we're looking for, so just go to the end of the
					//FlowElement and continue
					curPos = curEl.getAbsoluteStart() + curEl.textLength;
				}
				
			}
			
			return true;
		}
		
		/**
		 * @private
		 * canInsertSPBlock 
		 * 
		 * validate that we a valid selection to allow for insertion of a subBlock.  The rules are as
		 * follows:
		 * 	endPos > start
		 * 	the new block will not span multiple paragraphs
		 *  if the block is going into a SubParagraphGroupElementBase, it must not split the block:
		 * 		example:  Text 		- ABCDEFG with a link on CDE
		 * 		legal new Block		- D, CD, CDE, [n-chars]CDE[n1-chars]
		 * 		illegal new Block 	- [1 + n-chars]C[D], [D]E[1 + n-chars]
		 * 			exception - if the newBlock is the same class as the one we are trying to split
		 * 			then we can truncate the original and add its contents to the new one, or extend it
		 * 			as appropriate
		 * 
		 * @param theFlow The TextFlow that is containing the elements to validate.
		 * @param startPos The index value of the first position of the range in the TextFlow to test.
		 * @param endPos The index value following the end position of the range in the TextFlow to test.
		 * @param blockClass Class the class of the fbe we intend to insert.
		 */
		tlf_internal static function canInsertSPBlock(theFlow:TextFlow, startPos:int, endPos:int, blockClass:Class):Boolean
		{
			if(endPos <= startPos)
				return false;
				
			var anchorFBE:FlowGroupElement = theFlow.findAbsoluteFlowGroupElement(startPos);
			if(anchorFBE.getParentByType(blockClass))
				anchorFBE = anchorFBE.getParentByType(blockClass) as FlowGroupElement;
				
			var tailFBE:FlowGroupElement = theFlow.findAbsoluteFlowGroupElement(endPos - 1);
			if(tailFBE.getParentByType(blockClass))
				tailFBE = tailFBE.getParentByType(blockClass) as FlowGroupElement;
			
			//if these are the same FBEs then we are safe to insert a SubParagraphGroupElementBase
			if(anchorFBE == tailFBE)
				return true;
			//make sure that the two FBEs belong to the same paragraph!
			else if(anchorFBE.getParagraph() != tailFBE.getParagraph())
				return false;
			else if(anchorFBE is blockClass && tailFBE is blockClass)//they're the same class, OK to merge, split, etc...
				return true;
			else if(anchorFBE is SubParagraphGroupElementBase && !(anchorFBE is blockClass))
			{
				var anchorStart:int = anchorFBE.getAbsoluteStart();
				if(startPos > anchorStart && endPos > anchorStart + anchorFBE.textLength)
					return false;
			}
			else if((anchorFBE.parent is SubParagraphGroupElementBase || tailFBE.parent is SubParagraphGroupElementBase)
				&& anchorFBE.parent != tailFBE.parent)
			{
				//if either FBE parent is a SPGE and they are not the same, prevent the split.  
				return false;
			}	
			
			//if we got here, then the anchorFBE is OK, check the tail.  If endPos is pointing to the
			//0th character of a FlowGroupElement, we don't need to worry about the tail.
			if(tailFBE is SubParagraphGroupElementBase && !(tailFBE is blockClass) && endPos > tailFBE.getAbsoluteStart())
			{
				var tailStart:int = tailFBE.getAbsoluteStart();
				if(startPos < tailStart && endPos < tailStart + tailFBE.textLength)
					return false;
			}	
			return true;
		}
		
		/**
		 * @private flushSPBlock recursively walk a spg looking for elements of type spgClass.  On finding one,
		 * remove it's children and then remove the object itself.  Since spg's cannot hold children of the same type
		 * as themselves, recursion is only needed for spg's of a class other than that of spgClass.
		 * 
		 * example: subPB = <b>bar<a>other</a><b> extending an <a> element to include all of "other"
		 */ 
		tlf_internal static function flushSPBlock(subPB:SubParagraphGroupElementBase, spgClass:Class):void
		{
			var subParaIter:int = 0;
	
			//example, subPB has 2 elements, <span>bar</span> and <a><span>other</span></a>
			while(subParaIter < subPB.numChildren)
			{
				//subParaIter == 0, subFE = <span>bar</span> skip the FE and move to next
				//subParaIter == 1, subFE = <a><span>other</span></a> - is a spgClass
				var subFE:FlowElement = subPB.getChildAt(subParaIter);
				if(subFE is spgClass)
				{
					//subParaIter == 1, subFE = <a><span>other</span></a>
					var subChildFBE:FlowGroupElement = subFE as FlowGroupElement;
					while(subChildFBE.numChildren > 0)
					{
						//subFEChild = <span>other</span>
						var subFEChild:FlowElement = subChildFBE.getChildAt(0);
						//subFEChild = <a></a>
						subChildFBE.replaceChildren(0, 1);
						//subPB = <b>barother<a></a><b>
						subPB.replaceChildren(subParaIter, subParaIter, subFEChild);
					}
					
					//increment so that subParaIter points to the element we just emptied
					++subParaIter;
					//remove the empty child
					//subPB = <b>barother<b>
					subPB.replaceChildren(subParaIter, subParaIter + 1);
				}
				else if(subFE is SubParagraphGroupElementBase)
				{
					flushSPBlock(subFE as SubParagraphGroupElementBase, spgClass);
					++subParaIter;
				}
				else
					++subParaIter;//go to next child
			}
		}
		
		/** returns next paragraph in reading order after para. Used for merging paragraphs after delete.  */
		tlf_internal static function findNextParagraph(para:ParagraphElement):ParagraphElement
		{
			if (para)
			{
				var leaf:FlowLeafElement = para.getLastLeaf();
				leaf = leaf.getNextLeaf();
				if (leaf)
					return leaf.getParagraph();
			}
			return null;
		/*	var sibParagraph:ParagraphElement;
			if (para && para.parent)
			{
				var child:FlowGroupElement = para;
				var parent:FlowGroupElement = para.parent;
				
				var myidx:int = parent.getChildIndex(child);
				
				// go up the chain till not on last child
				while(myidx == parent.numChildren-1)
				{
					child = parent;
					parent = parent.parent;
					myidx = parent.getChildIndex(child);
				}
				if (myidx != parent.numChildren-1)
				{
					// go down the first child descendents till reach a paragraph
					var sibElement:FlowGroupElement = parent.getChildAt(myidx+1) as FlowGroupElement;
					while(sibElement && !(sibElement is ParagraphElement))
					{
						sibElement = sibElement.getChildAt(0) as FlowGroupElement;	
					}
					sibParagraph = sibElement as ParagraphElement;
				}
			}
			return sibParagraph; */
		}
		
		/** if parent is a singleton element, deletes it, then repeats deletion of singletons up the parent chain.  Used after paragraph merge. */
		tlf_internal static function removeEmptyParentChain(parent:FlowGroupElement):IMemento
		{
			var mementoList:MementoList = new MementoList(parent.getTextFlow());
			while(parent && (parent.numChildren == 0))
			{
				var grandParent:FlowGroupElement = parent.parent;
				if(grandParent)
				{
					var parentIdx:int = grandParent.getChildIndex(parent);
					mementoList.push(ModelEdit.removeElements(grandParent.getTextFlow(), grandParent, parentIdx, 1));
					//grandParent.replaceChildren(parentIdx, parentIdx+1);
				}
				parent = grandParent;
			}
			return mementoList;
		}
		
		/** Joins this paragraph's next sibling to this if it is a paragraph */
		static public function joinNextParagraph(para:ParagraphElement, inSameParent:Boolean):IMemento
		{		
			var nextPara:ParagraphElement = findNextParagraph(para);
			if (nextPara && (!inSameParent || para.parent == nextPara.parent))
				return joinToElement(para, nextPara);
			return null;
		}

		/** Joins this paragraph's next sibling to this if it is a paragraph */
		static public function joinToNextParagraph(para:ParagraphElement, inSameParent:Boolean):MementoList
		{		
			var sibParagraph:ParagraphElement = findNextParagraph(para);
			if (sibParagraph && (!inSameParent || para.parent == sibParagraph.parent))
				return joinToNextElement(para, sibParagraph);
			return null;
		}

		/** Joins this element2 to element1 -- all children of element2 added to end of element1 */
		static public function joinToElement(element1:FlowGroupElement, element2:FlowGroupElement):IMemento
		{	
			var list:MementoList;
			
			if (element1 && element2)
			{
		/*		list = new MementoList(element1.getTextFlow());
				
				var elementList:Array = element2.mxmlChildren;
				
				list.push(ModelEdit.removeElements(element2.getTextFlow(), element2, 0, element2.numChildren)); // remove children of the second element

				for(var i:int=0; i<elementList.length; ++i) // add them to the first element
				{
					list.push(ModelEdit.addElement(element1.getTextFlow(), elementList[i], element1, element1.numChildren));
				}
				// remove (empty) element2 and chain of any empty parents
				list.push(removeEmptyParentChain(element2));
				return list;
				*/
				return ModelEdit.joinElement(element2.getTextFlow(), element1, element2);
			}
			return list;
		}
		
		/** Joins this element1 to element2 -- all children of element1 added to front of element2 */
		static public function joinToNextElement(element1:FlowGroupElement, element2:FlowGroupElement):MementoList
		{		
			var list:MementoList;

			if (element1 && element2)
			{
				list = new MementoList(element1.getTextFlow());

				var elementList:Array = element1.mxmlChildren;
				list.push(ModelEdit.removeElements(element1.getTextFlow(), element1, 0, element1.numChildren)); // remove children of the first element
				for(var i:int=elementList.length - 1; i>=0; --i) // add them to the second element
				{
					list.push(ModelEdit.addElement(element2.getTextFlow(), elementList[i], element2, 0));
				}
				// remove (empty) element1 and chain of any empty parents
				list.push(removeEmptyParentChain(element1));
				return list;
			}
			return list;
		}
		
								
	}
}
