////////////////////////////////////////////////////////////////////////////////
//
//  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 UnitTest.Tests
{
	import UnitTest.ExtendedClasses.TestDescriptor;
	import UnitTest.ExtendedClasses.TestSuiteExtended;
	import UnitTest.ExtendedClasses.VellumTestCase;
	import UnitTest.Fixtures.TestConfig;
	
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.DisplayObjectContainer;
	import flash.display.Sprite;
	import flash.geom.Rectangle;
	import flash.text.engine.FontDescription;
	import flash.text.engine.FontWeight;
	import flash.text.engine.TextLine;
	import flash.utils.ByteArray;
	import flash.utils.getTimer;
	
	import flashx.textLayout.compose.StandardFlowComposer;
	import flashx.textLayout.compose.TextFlowLine;
	import flashx.textLayout.container.ContainerController;
	import flashx.textLayout.edit.EditManager;
	import flashx.textLayout.edit.IEditManager;
	import flashx.textLayout.elements.DivElement;
	import flashx.textLayout.elements.FlowElement;
	import flashx.textLayout.elements.FlowLeafElement;
	import flashx.textLayout.elements.GlobalSettings;
	import flashx.textLayout.elements.InlineGraphicElement;
	import flashx.textLayout.elements.LinkElement;
	import flashx.textLayout.elements.ListElement;
	import flashx.textLayout.elements.ListItemElement;
	import flashx.textLayout.elements.ParagraphElement;
	import flashx.textLayout.elements.SpanElement;
	import flashx.textLayout.elements.TCYElement;
	import flashx.textLayout.elements.TextFlow;
	import flashx.textLayout.formats.BlockProgression;
	import flashx.textLayout.formats.Direction;
	import flashx.textLayout.formats.FormatValue;
	import flashx.textLayout.formats.ITextLayoutFormat;
	import flashx.textLayout.formats.ListStyleType;
	import flashx.textLayout.formats.TextAlign;
	import flashx.textLayout.formats.TextLayoutFormat;
	import flashx.textLayout.property.*;
	import flashx.textLayout.tlf_internal;
	import flashx.undo.IUndoManager;
	import flashx.undo.UndoManager;
	
	import mx.core.FTETextField;
	import mx.utils.LoaderUtil;

	use namespace tlf_internal;

	public class FlowModelTest extends VellumTestCase
	{
		public function FlowModelTest(methodName:String, testID:String, testConfig:TestConfig, testXML:XML = null)
		{
			super(methodName, testID, testConfig);

			// Note: These must correspond to a Watson product area (case-sensitive)
			metaData.productArea = "Text Container";
			metaData.productSubArea = "Flow";
		}

		public static function suite(testConfig:TestConfig, ts:TestSuiteExtended):void
		{
			if (testConfig.writingDirection[0] == BlockProgression.TB && testConfig.writingDirection[1] == Direction.LTR)
			{
	   			ts.addTestDescriptor (new TestDescriptor (FlowModelTest, "basicAPITest1", testConfig ) );
	   			ts.addTestDescriptor (new TestDescriptor (FlowModelTest, "basicAPITest2", testConfig ) );
	   			ts.addTestDescriptor (new TestDescriptor (FlowModelTest, "basicAPITest3", testConfig ) );
	   			ts.addTestDescriptor (new TestDescriptor (FlowModelTest, "basicAPITest4", testConfig ) );
				ts.addTestDescriptor (new TestDescriptor (FlowModelTest, "basicAPITest5", testConfig ) );
				ts.addTestDescriptor (new TestDescriptor (FlowModelTest, "textFlowHostCharacterFormat", testConfig ) );
				ts.addTestDescriptor (new TestDescriptor (FlowModelTest, "iterateParagraphForward", testConfig ) );
				ts.addTestDescriptor (new TestDescriptor (FlowModelTest, "iterateParagraphBackward", testConfig ) );
				ts.addTestDescriptor (new TestDescriptor (FlowModelTest, "cascadeValidation", testConfig ) );
				ts.addTestDescriptor (new TestDescriptor (FlowModelTest, "elementMovingTest", testConfig ) );
				ts.addTestDescriptor (new TestDescriptor (FlowModelTest, "emptyTextFlowTests", testConfig ) );
				ts.addTestDescriptor (new TestDescriptor (FlowModelTest, "emptyElementCopyTests", testConfig ) );
				ts.addTestDescriptor (new TestDescriptor (FlowModelTest, "fontMappingTest", testConfig ) );
				ts.addTestDescriptor (new TestDescriptor (FlowModelTest, "insertLinkNoUpdateAPI", testConfig ) );
				ts.addTestDescriptor (new TestDescriptor (FlowModelTest, "insertLinkNoUpdateViaEditManager", testConfig ) );
				ts.addTestDescriptor (new TestDescriptor (FlowModelTest, "testUndo", testConfig ) );
				ts.addTestDescriptor (new TestDescriptor (FlowModelTest, "testFindControllerIndexAtPosition", testConfig ) );
				
				ts.addTestDescriptor (new TestDescriptor (FlowModelTest, "testFTETextField", testConfig ) );
				
				ts.addTestDescriptor (new TestDescriptor (FlowModelTest, "listItemInsertion", testConfig ) );
				ts.addTestDescriptor (new TestDescriptor (FlowModelTest, "replaceChildrenTest", testConfig ) );
				ts.addTestDescriptor (new TestDescriptor (FlowModelTest, "resolveFontLookupTest", testConfig ) );
				ts.addTestDescriptor (new TestDescriptor (FlowModelTest, "bindableSpan", testConfig ) );
			}
   		}

   		private var beginTime:int;
   		private function beginAPITest():void
   		{
   			beginTime = getTimer();
			SelManager.selectRange(-1,-1);
   		}
   		private function endAPITest():void
   		{
			SelManager.selectRange(0,0);
			SelManager.textFlow.flowComposer.updateAllControllers();
   		}

		/**
		 * Direct usage of the flow APIs. No validation - just look for crashes.
		 * This test changes the color of the entire text.
		 */
		public function basicAPITest1():void
		{
			// set the color on the entire flow
			beginAPITest();
			SelManager.textFlow.color = 0xff0000;
			endAPITest();
		}

		/**
		 * Direct usage of the flow APIs. No validation - just look for crashes.
		 * This test deletes every other character in the entire text.
		 */
		public function basicAPITest2():void
		{
			// delete every other character in the textflow
			beginAPITest();

			var idx:int = 0;
			while (idx < SelManager.textFlow.textLength)
			{
				var span:SpanElement = SelManager.textFlow.findLeaf(idx) as SpanElement;
				if (span)
				{
					var spanStart:int = span.getAbsoluteStart();
					span.replaceText(idx-spanStart,idx-spanStart+1,null);
				}
				idx++;

			}
			endAPITest();
		}

		/**
		 * Direct usage of the flow APIs. No validation - just look for crashes.
		 * This test adds another paragraph to the flow containing the text "Hello World"
		 * in 24 point font.
		 */
		public function basicAPITest3():void
		{
			// add a paragraph
			beginAPITest();
			var p:ParagraphElement = new ParagraphElement();
			var s:SpanElement = new SpanElement();
			s.text = "Hello world";
			s.fontSize = 24;
			p.replaceChildren(0,0,s);
			SelManager.textFlow.replaceChildren(SelManager.textFlow.numChildren,SelManager.textFlow.numChildren,p);
			endAPITest();
		}

		/**
		 * This test performs a series of changes and validates the changes after they're performed.
		 */
		public function basicAPITest4():void
		{
			// more comprehensive set of tests - several manipulations to the flow and then display it

			// generic begin to an API test
			beginAPITest();

			// get the textflow
			var textFlow:TextFlow = SelManager.textFlow;

			// remove all the textflow children
			textFlow.replaceChildren(0,textFlow.numChildren);
			assertTrue("expected no elements on the flow, but found " + textFlow.numChildren,
						textFlow.numChildren == 0);

			// create a paragraph
			var p:ParagraphElement = new ParagraphElement();

			// create a span
			var s:SpanElement = new SpanElement();
			s.text = "Hello world. ";
			s.fontSize = 24;

			// split the span
			var nextSpan:SpanElement = s.splitAtPosition(6) as SpanElement;
			// set the color - color can be a string or an unsigned integer
			nextSpan.color = "0xff";
			assertTrue("expected that the color would be 255, but found " + uint(nextSpan.format.color),
						uint(nextSpan.format.color) == 255);

			// put the two spans in the paragraph
			p.replaceChildren(0,0,s);
			CONFIG::debug { assertTrue("debugCheckFlowElement() failed after adding one span",
										p.debugCheckFlowElement() == 0); }
			p.replaceChildren(1,1,nextSpan);
			CONFIG::debug { assertTrue("debugCheckFlowElement() failed after adding second span",
										p.debugCheckFlowElement() == 0); }
			assertTrue("expected the element count to be 2, but it was " + p.numChildren,
						p.numChildren == 2);

			// add another span
			s = new SpanElement();
			s.text = "Start:"
			p.replaceChildren(0,0,s);
			CONFIG::debug { assertTrue("debugCheckFlowElement() failed after adding third span",
										p.debugCheckFlowElement() == 0); }

			// put the paragraph in the TextFlow
			textFlow.replaceChildren(0,0,p);
			assertTrue("text flow should have one element but has " + textFlow.numChildren,
						textFlow.numChildren == 1);
			CONFIG::debug { assertTrue("debugCheckFlowElement() failed after adding para to flow",
										textFlow.debugCheckFlowElement() == 0) }

			// make another paragraph
			p = new ParagraphElement();
			s = new SpanElement();
			p.replaceChildren(0,0,s);
			s.text="NEW FIRST PARAGRAPH";

			// set the paragraph attributes directly
			p.textIndent = 20;
			// set the paragraph attributes via clone and set
			var pa:TextLayoutFormat = new TextLayoutFormat(p.format);
			pa.textAlign = TextAlign.RIGHT;
			p.format = pa;

			// into the textFlow at the beginning
			textFlow.replaceChildren(0,0,p);
			CONFIG::debug {assertTrue("debugCheckFlowElement() failed after adding para to beginning",
										textFlow.debugCheckFlowElement() == 0); }

			// generic end to an API test
			endAPITest();
		}

		/**
		 * This test inserts an FE in the middle of a paragraph
		 */
		public function basicAPITest5():void
		{
			// more comprehensive set of tests - several manipulations to the flow and then display it

			// generic begin to an API test
			beginAPITest();

			// get the textflow
			var textFlow:TextFlow = SelManager.textFlow;

			// create a paragraph empty the flow and insert it
			var p:ParagraphElement = new ParagraphElement();
			textFlow.replaceChildren(0,textFlow.numChildren,p);

			// create a span
			var s:SpanElement = new SpanElement();
			s.text = "Hello world. ";
			s.fontSize = 24;

			// put it in the paragraph
			p.replaceChildren(0,0,s);

			// split the span
			var nextSpanElement:SpanElement = s.splitAtPosition(6) as SpanElement;
			assertTrue("Incorrect elementCount after split", p.numChildren == 2);

			// create and insert an image between the spans
			var image:InlineGraphicElement = new InlineGraphicElement();
			image.width = 19;
			image.height = 19;
			image.source = LoaderUtil.createAbsoluteURL(baseURL,"../../test/testFiles/assets/surprised.png");
			p.replaceChildren(1,1,image);

			assertTrue("failed length on new InlineGraphicElement", image.textLength == 1);
			assertTrue("failed elementCount after image insert", p.numChildren == 3);
			assertTrue("bad first child",p.getChildAt(0) is SpanElement);
			assertTrue("bad first child",p.getChildAt(1) is InlineGraphicElement);
			assertTrue("bad first child",p.getChildAt(2) is SpanElement);
			
			// set a userStyle on a ContainerController
			var saveFormat:ITextLayoutFormat = ContainerController.containerControllerInitialFormat;
			try
			{
				ContainerController.containerControllerInitialFormat = null;
				var controller:ContainerController = new ContainerController(new Sprite());
				controller.setStyle("foo","blah");
			}
			catch (e:Error)
			{
				ContainerController.containerControllerInitialFormat = saveFormat;
				throw(e);			
			}
			ContainerController.containerControllerInitialFormat = saveFormat;

			// generic end to an API test
			endAPITest();
		}

		/** Test setting hostCharacterFormat on the TextFlow */
		public function textFlowHostCharacterFormat():void
		{
			// generic begin to an API test
			beginAPITest();

			// get the textflow
			var textFlow:TextFlow = SelManager.textFlow;
			var leaf:FlowLeafElement = textFlow.getFirstLeaf();

			// make it red
			var cf:TextLayoutFormat = new TextLayoutFormat();
			cf.color = 0xff0000;
			textFlow.hostFormat = cf;
			assertTrue("host character format set color failed",leaf.computedFormat.color == 0xff0000);

			// make it blue
			textFlow.color = 0xff;
			assertTrue("textFlow character format color override failed",leaf.computedFormat.color == 0xff);

			// clear the blue
			textFlow.color = undefined;
			assertTrue("textFlow color clear failed",leaf.computedFormat.color == 0xff0000);

			// clear the hostCharacterFormat
			textFlow.hostFormat = null;
			assertTrue("host character format clear failed",leaf.computedFormat.color == 0);

			endAPITest();
		}

		private function initTextFlowAAA():TextFlow
		{
			var textFlow:TextFlow = new TextFlow();
			var p:ParagraphElement = new ParagraphElement();
			var span:SpanElement = new SpanElement();
			span.text = "aaa";
			p.replaceChildren(0, 0, span);
			textFlow.replaceChildren(0, 0, p);
			return textFlow;
		}

		// Insert a link to a paragraph that hasn't ever been updated.
		public function insertLinkNoUpdateAPI():void
		{
			var textFlow:TextFlow = new TextFlow();
			var p:ParagraphElement = new ParagraphElement();
			var link:LinkElement = new LinkElement();
			link.href = "http://www.cnn.com";
			link.target = "_self";
			var span:SpanElement = new SpanElement();
			span.text = "aaa";
			link.replaceChildren(0, 0, span);
			p.replaceChildren(0, 0, link);
			textFlow.replaceChildren(0, 0, p);
		}

		// Insert a link to a paragraph that hasn't ever been updated.
		public function insertLinkNoUpdateViaEditManager():void
		{
			var textFlow:TextFlow = initTextFlowAAA();
			var editManager:IEditManager = new EditManager();
			textFlow.interactionManager = editManager;

			editManager.selectRange(1,2);
			editManager.applyLink("http://livedocs.adobe.com/", "_self", true);
		}

		// undo in a flow that has no controllers
		public function testUndo():void
		{
			var textFlow:TextFlow = initTextFlowAAA();
			var undoManager:IUndoManager = new UndoManager();
			var editManager:IEditManager = new EditManager(undoManager);
			textFlow.interactionManager = editManager;

			editManager.selectRange(1,2);
			var format:TextLayoutFormat = new TextLayoutFormat();
			format.fontWeight = FontWeight.BOLD;
			editManager.applyLeafFormat(format);

			undoManager.undo();
		}

		private function createParaIterationModel():TextFlow
		{
			// Creates 3 divs, each have 4 paras
			const paraTotal:int = 4;
			var paraCount:int;
			const divTotal:int = 3;
			var divCount:int;

			var flow:TextFlow = new TextFlow();
			for (var j:int = 0; j < divTotal; j++)
			{
				var div:DivElement = new DivElement();
				for (var i:int = 0; i < paraTotal; i++)
				{
					var para:ParagraphElement = new ParagraphElement();
					var span:SpanElement = new SpanElement();
					span.text = paraCount.toString();
					para.addChild(span);
					div.addChild(para);
					paraCount++;
				}
				flow.addChild(div);
			}
			return flow;
		}

		public function iterateParagraphForward():void
		{
			var flow:TextFlow = createParaIterationModel();
			var para:ParagraphElement = flow.getFirstLeaf().getParagraph();
			var i:int = 0;
			while (para != null)
			{
				var cStr:String = para.getText();
				assertTrue("Text not as expected", int(cStr) == i);
				para = para.getNextParagraph();
				i++;
			}
			assertTrue("Unexpected paragraph count", i == 12);
		}

		public function iterateParagraphBackward():void
		{
			//const kParaTerminator:String = '\u2029';

			var flow:TextFlow = createParaIterationModel();
			var para:ParagraphElement = flow.getLastLeaf().getParagraph();
			var i:int = 11;
			//These two tests are no longer valid due to PARB changes to removed the terminator
			//parameter from getText on a paragraph element.
			//
			//var terminatorTestStr:String = para.getText("\n");
			//assertTrue("Should have newline as terminator", terminatorTestStr.substr(terminatorTestStr.length - 1, 1) == '\n');
			//terminatorTestStr = para.getText();
			//assertTrue("Should have paragraph terminator as terminator", terminatorTestStr.substr(terminatorTestStr.length - 1, 1) == kParaTerminator);
			while (para != null)
			{
				var cStr:String = para.getText();
				assertTrue("Text not as expected", int(cStr) == i);
				para = para.getPreviousParagraph();
				i--;
			}
			assertTrue("Unexpected paragraph count", i == -1);
		}
		public function cascadeValidation():void
		{
			var flow:TextFlow = new TextFlow();
			var para:ParagraphElement = new ParagraphElement();
			var span:SpanElement = new SpanElement();
			flow.addChild(para);
			para.addChild(span);
			flow.backgroundColor = 0xff;
			assertTrue("backgroundColor should not inherit",TextLayoutFormat.backgroundColorProperty.inherited == false);
			assertTrue("bad flow backGroundColor", flow.computedFormat.backgroundColor == 0xff);
			assertTrue("bad para backGroundColor", para.computedFormat.backgroundColor == TextLayoutFormat.backgroundColorProperty.defaultValue);
			assertTrue("bad span backGroundColor", span.computedFormat.backgroundColor == TextLayoutFormat.backgroundColorProperty.defaultValue);
		}

		// tests api change to automatically remove a flowelements children when using replaceChildren
		public function elementMovingTest():void
		{
			var lengthBefore:int;

			// this flow should have two paragraphs as children
			var flow:TextFlow = SelManager.textFlow.deepCopy() as TextFlow;	// clone the flow

			var firstPara:FlowElement = flow.getChildAt(0);
			lengthBefore = flow.textLength;
			//firstPara.parent.removeChild(firstPara);	// soon to no longer be needed
			//assertTrue("elementMovingTest: removing para incorrect lengths",flow.textLength == lengthBefore-firstPara.textLength);

			lengthBefore = SelManager.textFlow.textLength;
			SelManager.textFlow.addChild(firstPara);
			assertTrue("elementMovingTest: adding para incorrect lengths",SelManager.textFlow.textLength == lengthBefore+firstPara.textLength);

			var lastLeaf:FlowElement = flow.getLastLeaf();
			var lastLeafLength:int = lastLeaf.textLength;
			//lastLeaf.parent.removeChild(lastLeaf);	// soon to no longer be needed
			lengthBefore = SelManager.textFlow.textLength;
			SelManager.textFlow.getLastLeaf().parent.addChild(lastLeaf);
			assertTrue("elementMovingTest: adding span incorrect lengths",SelManager.textFlow.textLength == lengthBefore+lastLeafLength-1);
		}

		// Empty Flow Tests - verify that empty/partially empty TextFlow's are normalized correctly
		public function emptyTextFlowTests():void
		{
			var tf:TextFlow;

			// just an empty TextFlow
			tf = new TextFlow();
			tf.flowComposer.addController(new ContainerController(new Sprite()));
			tf.flowComposer.updateAllControllers();

			// empty TextFlow with paragraph
			tf = new TextFlow();
			tf.addChild(new ParagraphElement());
			tf.flowComposer.addController(new ContainerController(new Sprite()));
			tf.flowComposer.updateAllControllers();

			// empty TextFlow with paragraph and ILG
			tf = new TextFlow();
			var p:ParagraphElement = new ParagraphElement();
			p.addChild(new InlineGraphicElement());
			tf.addChild(p);
			tf.flowComposer.addController(new ContainerController(new Sprite()));
			tf.flowComposer.updateAllControllers();

			// empty TextFlow with paragraph and empty LinkElement
			tf = new TextFlow();
			p = new ParagraphElement();
			p.addChild(new LinkElement());
			tf.addChild(p);
			tf.flowComposer.addController(new ContainerController(new Sprite()));
			tf.flowComposer.updateAllControllers();

			// empty TextFlow with paragraph and empty TCYElement
			tf = new TextFlow();
			p = new ParagraphElement();
			p.addChild(new TCYElement());
			tf.addChild(p);
			tf.flowComposer.addController(new ContainerController(new Sprite()));
			tf.flowComposer.updateAllControllers();

			// a more complex example
			tf = new TextFlow();
			p = new ParagraphElement();
			var tcy:TCYElement = new TCYElement();
			tcy.addChild(new InlineGraphicElement());
			tcy.addChild(new SpanElement());
			p.addChild(tcy);
			tf.addChild(p);
			tcy.removeChildAt(1);
			tf.flowComposer.addController(new ContainerController(new Sprite()));
			tf.flowComposer.updateAllControllers();

			// several empty spans
			tf = new TextFlow();
			p = new ParagraphElement();
			tf.addChild(p);
			p.addChild(new SpanElement());
			p.addChild(new SpanElement());
			p.addChild(new SpanElement());
			tf.flowComposer.addController(new ContainerController(new Sprite()));
			tf.flowComposer.updateAllControllers();
		}
		
		public function emptyElementCopyTests():void
		{
			var elemList:Array = GeneralFunctionsTest.childParentTable[0];
			for (var idx:int = 1; idx < elemList.length; idx++)
			{
				var elem:FlowElement = new elemList[idx];
				elem.shallowCopy();
				elem.deepCopy();
			}
		}

		private function validateBitmap(actual:Bitmap, expected:Bitmap):Boolean
		{
			actual.bitmapData.draw(expected, null, null, "difference");
			var bounds:Rectangle = new Rectangle(0, 0, actual.width, actual.height);
			var diffPixels:ByteArray = actual.bitmapData.getPixels(bounds);
			diffPixels.position = 0;
			while (diffPixels.bytesAvailable > 0)
			{
				if (diffPixels.readByte() > 0)
					return false;
			}

			return true;
		}

		private function myFontMapper(fd:FontDescription):void
		{
			if (fd.fontName == "Arial Black")
			{
				fd.fontName = "Arial";
				fd.fontWeight = FontWeight.BOLD;
			}
		}

		/** Tests fontMapping */
		public function fontMappingTest():void
		{
			var textFlow:TextFlow = SelManager.textFlow;
			var container:DisplayObjectContainer = DisplayObjectContainer(textFlow.flowComposer.getControllerAt(0).container);

			textFlow.fontFamily = "Arial";
			textFlow.fontWeight = FontWeight.BOLD;
			textFlow.flowComposer.updateAllControllers();

			var arialBoldBits:BitmapData = new BitmapData(container.width,container.height);
			arialBoldBits.draw(container as DisplayObjectContainer);
			var arialBoldData:Bitmap = new Bitmap(arialBoldBits);

			textFlow.fontFamily = "Arial Black";
			textFlow.fontWeight = undefined;
			textFlow.flowComposer.updateAllControllers();

			var arialBlackBits:BitmapData = new BitmapData(container.width,container.height);
			arialBlackBits.draw(container as DisplayObjectContainer);
			var arialBlackData:Bitmap = new Bitmap(arialBlackBits);

			GlobalSettings.fontMapperFunction = myFontMapper;
			textFlow.invalidateAllFormats();

			try
			{
				textFlow.flowComposer.updateAllControllers();
			}
			finally
			{
				GlobalSettings.fontMapperFunction = null;
				textFlow.invalidateAllFormats();
			}

			var mappedBits:BitmapData = new BitmapData(container.width,container.height);
			mappedBits.draw(container as DisplayObjectContainer);
			var mappedData:Bitmap = new Bitmap(mappedBits);

			assertTrue("font mapping failed", validateBitmap(mappedData, arialBoldData));

			textFlow.flowComposer.updateAllControllers();

			var mappingClearedBits:BitmapData = new BitmapData(container.width,container.height);
			mappingClearedBits.draw(container as DisplayObjectContainer);
			var mappingClearedData:Bitmap = new Bitmap(mappingClearedBits);

			assertTrue("clearing font mapping failed", validateBitmap(mappingClearedData, arialBlackData));

		}

		/** test the binary search algorithm which in findControllerIndexAtPosition - tricky bits wrt handling of zero length containers */
		public function testFindControllerIndexAtPosition():void
		{
			var s:Sprite = new Sprite();	// scratch
			var controller:ContainerController;	// scratch
			var composer:StandardFlowComposer = new StandardFlowComposer();
			// ideally shouldn't need TextFlow but because containercontrollers find their owning composer via the textflow its needed
			var textFlow:TextFlow = new TextFlow();
			textFlow.flowComposer = composer;
			textFlow.mxmlChildren = [ "012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678" ];

			controller = new ContainerController(s);
			controller.verticalScrollPolicy = "off";
			composer.addController(controller);
			controller.setTextLength(100);
			controller.verticalScrollPolicy = "off";

			assertTrue("Bad result in findControllerIndexAtPosition 9",composer.findControllerIndexAtPosition(0)== 0);
			assertTrue("Bad result in findControllerIndexAtPosition 10",composer.findControllerIndexAtPosition(100,true)== 0);
			assertTrue("Bad result in findControllerIndexAtPosition 11",composer.findControllerIndexAtPosition(100,false)== -1);

			for (var idx1:int  = 0; idx1 < 4; idx1++)
			{
				for (var idx2:int = 0; idx2 < 4 ; idx2++)
				{
					var idx:int;

					composer = new StandardFlowComposer();
					textFlow = new TextFlow();
					textFlow.flowComposer = composer;
					textFlow.mxmlChildren = [ "012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678" ];

					// add some empties
					for (idx = 0; idx < idx1; idx++)
						composer.addController(new ContainerController(s));
					// add one of length one
					controller = new ContainerController(s);
					controller.verticalScrollPolicy = "off";	// scrolling confuses it
					composer.addController(controller);
					controller.setTextLength(100);				// internal API
					// add some empties
					for (idx = 0; idx < idx2; idx++)
						composer.addController(new ContainerController(s));
					assertTrue("Bad result in findControllerIndexAtPosition 1",composer.findControllerIndexAtPosition(0)== 0);
					assertTrue("Bad result in findControllerIndexAtPosition 2",composer.findControllerIndexAtPosition(0,true)== 0);
					assertTrue("Bad result in findControllerIndexAtPosition 3",composer.findControllerIndexAtPosition(100,true)== idx1);
					assertTrue("Bad result in findControllerIndexAtPosition 4",composer.findControllerIndexAtPosition(100,false)== -1);
					// add one with some length
					textFlow.mxmlChildren = [ "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678" ];
					controller.setTextLength(100);
					controller = new ContainerController(s);
					controller.verticalScrollPolicy = "off";	// scrolling confuses it
					composer.addController(controller);
					controller.setTextLength(100);				// internal API
					assertTrue("Bad result in findControllerIndexAtPosition 5",composer.findControllerIndexAtPosition(100,true)== idx1);
					assertTrue("Bad result in findControllerIndexAtPosition 6",composer.findControllerIndexAtPosition(100,false)== idx1+1);
					assertTrue("Bad result in findControllerIndexAtPosition 7",composer.findControllerIndexAtPosition(200,true)== idx1+idx2+1);
					assertTrue("Bad result in findControllerIndexAtPosition 8",composer.findControllerIndexAtPosition(200,false)== -1);
				}
			}

		}
		
		private static function checkListLines(textFlow:TextFlow,numLines:int,prefix:String):void
		{
			for (var idx:int = 0; idx < numLines; idx++)
			{
				var tfl:TextFlowLine = textFlow.flowComposer.getLineAt(idx);
				assertTrue(prefix+": Missing TextFlowLine: "+idx,tfl != null);
				var textLine:TextLine = tfl.getTextLine();
				assertTrue(prefix+": Missing TextLine: "+idx,textLine != null);
				var numberLine:TextLine = textLine.getChildAt(0) as TextLine;
				assertTrue(prefix+": Missing NumberLine: "+idx,numberLine != null);
				/* var numberString:String = numberLine.userData as String;
				var expectedString:String = (idx+1).toString() + ".";	// for numeric lists
				assertTrue(prefix+": NumberLine missing userData: "+idx,numberString != null);
				assertTrue(prefix+": Incorrect NumberLine userData: "+idx,numberLine.userData as String == expectedString); 
				assertTrue(prefix+": Incorrect NumberLine rawTextLength: "+idx,numberString.length+1 == numberLine.rawTextLength); */
			}
		}
		
		public function listItemInsertion():void
		{
			// some validations that ensure ListElement is correctly setup for list processing
			
			// every ListStyleType must have an entry in ListElement.listSuffixes
			var handler:EnumPropertyHandler = TextLayoutFormat.listStyleTypeProperty.findHandler(EnumPropertyHandler) as EnumPropertyHandler;
			assertTrue("listItemInsertion: missing handler for ListStyleType", handler != null && handler.range != null);

			var	range:Object = handler.range;
			var value:String;
			
			var numberedListStyles:Object = { };
			for (value in ListElement.algorithmicListStyles)
			{
				assertTrue("listItemInsertion: table entry duplicated",numberedListStyles[value] === undefined);
				numberedListStyles[value] = ListElement.algorithmicListStyles[value];
			}
			for (value in ListElement.numericListStyles)
			{
				assertTrue("listItemInsertion: table entry duplicated",numberedListStyles[value] === undefined);
				numberedListStyles[value] = ListElement.numericListStyles[value];
			}
			for (value in ListElement.alphabeticListStyles)
			{
				assertTrue("listItemInsertion: table entry duplicated",numberedListStyles[value] === undefined);
				numberedListStyles[value] = ListElement.alphabeticListStyles[value];
			}
			
			for (value in range)
			{
				if (value != FormatValue.INHERIT)
				{
					// must be a numbered list or an unnumbered list but not both
					assertTrue("listItemInsertion: listStyleType must be numbered or unnumbered but not both: "+value,
						numberedListStyles[value] !== undefined && ListElement.constantListStyles[value] === undefined
						|| numberedListStyles[value] === undefined && ListElement.constantListStyles[value] !== undefined)
					// numbered lists must have a suffix
					if ( ListElement.constantListStyles[value] === undefined)
						assertTrue("listItemInsertion: missing suffix property: " + value,ListElement.listSuffixes[value] !== undefined);
				}
			}
			
			// verify that all constantListStyles are in range
			for (value in ListElement.constantListStyles)
				assertTrue("listItemInsertion: invalid value in constantListStyles: " + value, range[value] !== undefined);
			// verify that all numberedListStyles are in range
			for (value in numberedListStyles)
				assertTrue("listItemInsertion: invalid value in numberedListStyles: " + value, range[value] !== undefined);
			// verify that all listSuffixes are in range
			for (value in ListElement.listSuffixes)
				assertTrue("listItemInsertion: invalid value in listSuffixes: " + value, range[value] !== undefined);			
				
			SelManager.selectRange(0,0);

			// remove all the children and put in a list
			var textFlow:TextFlow = SelManager.textFlow;
			
			textFlow.replaceChildren(0,textFlow.numChildren);
			
			var list:ListElement = new ListElement();
			list.listStyleType = ListStyleType.DECIMAL;
			
			textFlow.addChild(list);
			var item:ListItemElement = new ListItemElement();
			list.addChild(item);
			
			textFlow.flowComposer.updateAllControllers();
			
			assertTrue("listItemInsertion: incorrect normalize",textFlow.findAbsoluteParagraph(0).parent == item);
			
			// append two items and compose
			list.addChild(new ListItemElement());
			list.addChild(new ListItemElement());
			textFlow.flowComposer.updateAllControllers();
			
			// check the three textlines
			checkListLines(textFlow,3,"listItemInsertion1");
			
			// now insert a brand new ListItem at the head and verify
			list.replaceChildren(0,0,new ListItemElement());
			textFlow.flowComposer.updateAllControllers();
			
			// check four textlines
			checkListLines(textFlow,4,"listItemInsertion2");
			
			// remove a list item
			list.removeChildAt(1);
			textFlow.flowComposer.updateAllControllers();
			
			// check three textLines
			checkListLines(textFlow,3,"listItemInsertion3");
			
			// add another list in the first ListItemElement
			item = list.getChildAt(0) as ListItemElement;
			var newList:ListElement = new ListElement();
			item.addChild(newList);
			textFlow.flowComposer.updateAllControllers();
			
			// assert the empty list is deleted
			assertTrue("listItemInsertion: newList not normalized",newList.numChildren == 1);

		}
		
		public function testFTETextField():void
		{
			// use the TextFlow's container
			var fieldParent:Sprite = SelManager.textFlow.flowComposer.getControllerAt(0).container;
			// remove the controller so the the textFlow isn't displayed in it
			SelManager.textFlow.flowComposer.removeControllerAt(0);
			
			var field:FTETextField = new FTETextField();
			field.htmlText = "Hello world";
			fieldParent.addChild(field);
		}
		
		public function replaceChildrenTest():void
		{
			SelManager.selectRange(0,0);
			
			// remove all the children 
			var textFlow:TextFlow = SelManager.textFlow;
			textFlow.replaceChildren(0,textFlow.numChildren);
			
			var p:ParagraphElement = new ParagraphElement();
			textFlow.addChild(p);
			
			var link:LinkElement = new LinkElement();
			link.href = "XXX";
			p.addChild(link);
			var span:SpanElement = new SpanElement();
			span.text = "Hello, ";
			span.fontSize = 24;
			link.addChild(span);
			
			var link2:LinkElement = new LinkElement();
			link2.href = "YYY";
			p.addChild(link2);
			
			var span2:SpanElement = new SpanElement();
			span2.text = "world ";
			span2.fontSize = 24;
			link2.addChild(span2);
			
			textFlow.flowComposer.updateAllControllers();
			
			link.replaceChildren(link2.numChildren,link2.numChildren,link2.mxmlChildren);
			p.removeChild(link2);
			textFlow.flowComposer.updateAllControllers();
			
			assertTrue("replaceChildrenTest: extra line - look for extra terminator",textFlow.flowComposer.numLines == 1);
		}
		
		private function myFontLookup(context:mySwfContext, tlf:ITextLayoutFormat):Function
		{
			return myFontLookup;
		}
		
		public function resolveFontLookupTest():void
		{
			var textFlow:TextFlow = SelManager.textFlow;
			
			textFlow.fontFamily = "Arial";
			textFlow.fontWeight = FontWeight.BOLD;
			textFlow.fontLookup = "device";
			textFlow.flowComposer.updateAllControllers();
			
			var swfContext:mySwfContext = new mySwfContext();
			try
			{
				GlobalSettings.resolveFontLookupFunction = myFontLookup(swfContext, textFlow.format);
				textFlow.flowComposer.updateAllControllers();
				assertTrue ("fontLookup not matched.", textFlow.fontLookup = swfContext.myFontlookup);
			}
			finally
			{
				GlobalSettings.resolveFontLookupFunction = null;
			}
		}
		
		public function bindableSpan():void
		{
			// Bindable span should not lose its formatting
			var textFlow:TextFlow = new TextFlow();
			var paragraph:ParagraphElement =  new ParagraphElement();
			var span1:SpanElement = new SpanElement();
			var span2:SpanElement = new SpanElement();
			var format:TextLayoutFormat = new TextLayoutFormat();
			format.fontWeight = FontWeight.BOLD;
			span2.format = format;
			paragraph.mxmlChildren = [ span1, span2 ];
			textFlow.mxmlChildren = [ paragraph ];
			textFlow.flowComposer.addController(new ContainerController(new Sprite()));
			textFlow.flowComposer.compose();		// force normalize
			assertTrue("Spans should not be merged!", span2.parent == span1.parent && paragraph.numChildren == 2);
			assertTrue("Formatting on second span should be preserved!", span2.fontWeight == FontWeight.BOLD);
		}
	}
}

import flash.text.engine.FontLookup;
import flashx.textLayout.compose.ISWFContext;
import flashx.textLayout.elements.FlowElement;
import flashx.textLayout.elements.TextFlow;
import flashx.textLayout.formats.TextLayoutFormat;

class mySwfContext implements ISWFContext
{	
	public var myFontlookup:String = FontLookup.EMBEDDED_CFF;
	
	public function callInContext(fn:Function, thisArg:Object, argsArray:Array, returns:Boolean=true):*
	{
		var tf:TextFlow = thisArg as TextFlow;
		tf.fontLookup = FontLookup.EMBEDDED_CFF;
		if (returns)
			return fn.apply(thisArg, argsArray);
		fn.apply(thisArg, argsArray);
	}
	
}
