////////////////////////////////////////////////////////////////////////////////
//
//  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.TestConfigurationLoader;
	import UnitTest.ExtendedClasses.VellumTestCase;
	import UnitTest.Fixtures.TestCaseVo;
	import UnitTest.Fixtures.TestConfig;

	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.IBitmapDrawable;
	import flash.events.*;
	import flash.geom.Matrix;
	import flash.geom.Rectangle;
	import flash.text.engine.TabAlignment;
	import flash.text.engine.TextLine;
	import flash.utils.ByteArray;

	import flashx.textLayout.compose.TextFlowLine;
	import flashx.textLayout.elements.*;
	import flashx.textLayout.formats.*;
	import flashx.textLayout.property.NumberPropertyHandler;
	import flashx.textLayout.property.Property;
	import flashx.textLayout.tlf_internal;

	import org.flexunit.asserts.assertTrue;

	use namespace tlf_internal;

	[TestCase(order=40)]
	[RunWith("org.flexunit.runners.Parameterized")]
 	public class ParagraphTest extends VellumTestCase
	{
		[DataPoints(loader=backgroundcolorchangeTestLoader)]
		[ArrayElementType("UnitTest.Fixtures.TestCaseVo")]
		public static var backgroundcolorchangeTestDp:Array;

		public static var backgroundcolorchangeTestLoader:TestConfigurationLoader = new TestConfigurationLoader("../../test/testCases/ParagraphTest.xml", "backgroundcolorchangeTest");

		public function ParagraphTest()
		{
			super("", "ParagraphTest", TestConfig.getInstance());

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

		[Before]
		override public function setUpTest():void
		{
			super.setUpTest();
		}

		[After]
		override public function tearDownTest():void
		{
			super.tearDownTest();
		}

		/* ************************************************************** */
		/* Alignment Tests */
		/* ************************************************************** */

		/**
		 * Get a short selection and set the alignment to left align and
		 * check that it is set correctly.
		 */
		[Test]
		public function alignLeftTest():void
		{
			// Set the selection.
			var startIndx:int = 10;
			var endIndx:int = 20;
			SelManager.selectRange(startIndx,endIndx);
			// Set the alignment.
			setAlignment(TextAlign.LEFT);
			// Confirm the alignment was set.
			assertTrue("alignment is not left - it's " + getAlignment(), getAlignment() == TextAlign.LEFT);
		}

		/**
		 * Get a short selection and set the alignment to right align and
		 * check that it is set correctly.
		 */
		[Test]
		public function alignRightTest():void
		{
			// Set the selection.
			var startIndx:int = 20;
			var endIndx:int = 40;
			SelManager.selectRange(startIndx,endIndx);
			// Set the alignment.
			setAlignment(TextAlign.RIGHT);
			// Confirm the alignment was set.
			assertTrue("alignment is not right - it's " + getAlignment(), getAlignment() == TextAlign.RIGHT);
		}

		/**
		 * Set the alignment to right align for all of the text and
		 * check that it is set correctly.
		 */
		[Test]
		public function alignAllRightTest():void
		{
			// Set the selection /
			var startIndx:int = 0;
			var endIndx:int = SelManager.textFlow.textLength - 1;
			SelManager.selectRange(startIndx,endIndx);  // select across paragraphs KJT
			// Set the alignment.
			setAlignment(TextAlign.RIGHT);
			// Confirm the alignment was set.
			assertTrue("alignment is not right - it's " + getAlignment(), getAlignment() == TextAlign.RIGHT);
		}

		/**
		 * Set the alignment to START align for all of the text and
		 * check that it is set correctly.
		 */
		[Test]
		public function alignStartTest():void
		{
			// Set the selection.
			var startIndx:int = 10;
			var endIndx:int = 20;
			SelManager.selectRange(startIndx,endIndx);
			// Set the alignment.
			setAlignment(TextAlign.START);
			// Confirm the alignment was set.
			assertTrue("alignment should be " + TextAlign.START + " but, actually is " + getAlignment(), getAlignment() == TextAlign.START);
		}

		/**
		 * Set the alignment to END align for all of the text and
		 * check that it is set correctly.
		 */
		[Test]
		public function alignEndTest():void
		{
			// Set the selection.
			var startIndx:int = 20;
			var endIndx:int = 40;
			SelManager.selectRange(startIndx,endIndx);
			// Set the alignment.
			setAlignment(TextAlign.END);
			// Confirm the alignment was set.
			assertTrue("alignment should be " + TextAlign.END + " but, actually is " + getAlignment(), getAlignment() == TextAlign.END);
		}


		/**
		 * Get a short selection and set the alignment to center align and
		 * check that it is set correctly.
		 */
		[Test]
		public function alignCenterTest():void
		{
			// Set the selection.
			var startIndx:int = 10;
			var endIndx:int = 20;
			SelManager.selectRange(startIndx,endIndx);
			// Set the alignment.
			setAlignment(TextAlign.CENTER);
			// Confirm the alignment was set.
			assertTrue("alignment is not center - it's " + getAlignment(), getAlignment() == TextAlign.CENTER);

		}

		/**
		 * Get a short selection and set the alignment to justify "all including last" and
		 * check that it is set correctly.
		 */
		[Test]
		public function alignJustifyAllTest():void
		{
			// Set the selection.
			var startIndx:int = 10;
			var endIndx:int = 20;
			SelManager.selectRange(startIndx,endIndx);
			// Set the alignment.
			setAlignment(TextAlign.JUSTIFY);
			setAlignmentLast(TextAlign.JUSTIFY);
			// Confirm the alignment was set.
			assertTrue("alignment is not justify - it's " + getAlignment() + " and " + getAlignmentLast(),
						getAlignment() == TextAlign.JUSTIFY && getAlignmentLast() == TextAlign.JUSTIFY);
		}

		/**
		 * Get a short selection and set the alignment to justify "all but last" and
		 * check that it is set correctly.
		 */
		[Test]
		public function alignJustifyAllButLastTest():void
		{
			// Set the selection.
			var startIndx:int = 10;
			var endIndx:int = 20;
			SelManager.selectRange(startIndx,endIndx);
			// Set the alignment.
			setAlignment(TextAlign.JUSTIFY);
			// Confirm the alignment was set.
			assertTrue("alignment is not justify - it's " + getAlignment(), getAlignment() == TextAlign.JUSTIFY);
		}

		/**
		 * Get a short selection and set the alignment to justify with last line start, end, left, center, right and
		 * check that it is set correctly.
		 */
		[Test]
		public function justifyWithLastLineStart():void
		{
			// Set the selection.
			var startIndx:int = 10;
			var endIndx:int = 20;
			SelManager.selectRange(startIndx,endIndx);
			// Set the alignment.
			setAlignment(TextAlign.JUSTIFY);
			setAlignmentLast(TextAlign.START);
			// Confirm the alignment was set.
			assertTrue("alignment should be " + TextAlign.JUSTIFY + " but, actually is " + getAlignment(),
				getAlignment() == TextAlign.JUSTIFY);
			assertTrue("last line alignment should be " + TextAlign.START + " but, actually is " + getAlignmentLast(),
				getAlignmentLast() == TextAlign.START);
		}

		[Test]
		public function justifyWithLastlineEnd():void
		{
			var startIndx:int = 10;
			var endIndx:int = 20;
			SelManager.selectRange(startIndx, endIndx);

			setAlignment(TextAlign.JUSTIFY);
			setAlignmentLast(TextAlign.END);

			assertTrue("alignment should be " + TextAlign.JUSTIFY + " but, actually is " + getAlignment(),
				getAlignment() == TextAlign.JUSTIFY);
			assertTrue("last line alignment should be " + TextAlign.END + " but, actually is " + getAlignmentLast(),
				getAlignmentLast() == TextAlign.END);
		}

		[Test]
		public function justifyWithLastlineLeft():void
		{

			var startIndx:int = 10;
			var endIndx:int = 20;
			SelManager.selectRange(startIndx, endIndx);

			setAlignment(TextAlign.JUSTIFY);
			setAlignmentLast(TextAlign.LEFT);

			assertTrue("alignmnet should be " + TextAlign.JUSTIFY + " but, actually is " + getAlignment(),
				getAlignment() == TextAlign.JUSTIFY);
			assertTrue("last line alignment should be " + TextAlign.JUSTIFY + " but, actually is " + getAlignmentLast(),
				getAlignmentLast() == TextAlign.LEFT);
		}

		[Test]
		public function justifyWithLastlineCenter():void
		{
			var startIndx:int = 10;
			var endIndx:int = 20;
			SelManager.selectRange(startIndx, endIndx);

			setAlignment(TextAlign.JUSTIFY);
			setAlignmentLast(TextAlign.CENTER);

			assertTrue("alignmnet should be " + TextAlign.JUSTIFY + " but, actually is " + getAlignment(),
				getAlignment() == TextAlign.JUSTIFY);
			assertTrue("last line alignment should be " + TextAlign.CENTER + " but, actually is " + getAlignmentLast(),
				getAlignmentLast() == TextAlign.CENTER);
		}

		[Test]
		public function justifyWithLastlineRight():void
		{
			var startIndx:int = 10;
			var endIndx:int = 20;
			SelManager.selectRange(startIndx, endIndx);

			setAlignment(TextAlign.JUSTIFY);
			setAlignmentLast(TextAlign.RIGHT);

			assertTrue("alignment should be " + TextAlign.JUSTIFY + " but, actually is " + getAlignment(),
				getAlignment() == TextAlign.JUSTIFY);
			assertTrue("last lie alignmnet shold be " + TextAlign.RIGHT + " but, actually is " + getAlignmentLast(),
				getAlignmentLast() == TextAlign.RIGHT);
		}

		[Test]
		public function onlyLastlineSet():void
		{
			var startIndx:int = 10;
			var endIndx:int = 20;
			SelManager.selectRange(startIndx, endIndx);

			setAlignmentLast(TextAlign.RIGHT);

			assertTrue("alignment should be " + TextAlign.START + " (default) but, actually is " + getAlignment(),
				getAlignment() == TextAlign.START);
			assertTrue("last lie alignmnet shold be " + TextAlign.RIGHT + " but, actually is " + getAlignmentLast(),
				getAlignmentLast() == TextAlign.RIGHT);
		}

		/**
		 * Get a short selection and set the textJustify to INTER_WORD and
		 * check that it is set correctly.
		 */
		[Test]
		public function justifyInterWordTest():void
		{
			// Set the selection.
			var startIndx:int = 10;
			var endIndx:int = 20;
			SelManager.selectRange(startIndx,endIndx);
			// Set the alignment.
			setTextJustify(TextJustify.INTER_WORD);
			// Confirm the alignment was set.
			assertTrue("textJustify is not interWord - it's " + getTextJustify(),
						getTextJustify() == TextJustify.INTER_WORD);
		}

		/**
		 * Set textJustify to INTER_WORD and DISTRIBUTE and verify
		 * that the spacing between glyphs is different on first line.
		 *
		 * Test with both last line set to JUSTIFY and to LEFT.
		 */
		[Test]
		public function justifyLetterSpacingFirstLine():void
		{
			justifyInterWordVsDistributeCore(false, false);
			justifyInterWordVsDistributeCore(false, true);
		}

		/**
		 * Set textJustify to INTER_WORD and DISTRIBUTE and verify
		 * that the spacing between glyphs is different on last line
		 * with last line set to JUSTIFY
		 */
		[Test]
		public function justifyLetterSpacingLastLineJustify():void
		{
			justifyInterWordVsDistributeCore(true, true);
		}

		/**
		 * Set textJustify to INTER_WORD and DISTRIBUTE and verify
		 * that the spacing between glyphs is not different on last line
		 * with last line justification set to LEFT
		 */
		[Test]
		public function justifyLetterSpacingLastLineNoJustify():void
		{
			justifyInterWordVsDistributeCore(true, false);
		}


		private function justifyInterWordVsDistributeCore(lastLine:Boolean, justifyLastLine:Boolean):void
		{
			var longWordText:String = "Longlonglonglonglonglong \
Longlonglonglonglonglong Longlonglonglonglonglong Longlonglonglonglonglong \
Longlonglonglonglonglong Longlonglonglonglonglong Longlonglonglonglonglong \
Longlonglonglonglonglong Longlonglonglonglonglong Longlonglonglonglonglong \
LonglonglonglonglonglongLong longlonglonglonglong Longlonglonglonglonglong.";
			var longWordTextLastPosition:int = longWordText.length - 1;

			SelManager.selectAll();
		 	SelManager.insertText(longWordText);

		 	SelManager.selectRange(1,1);
			setAlignment(TextAlign.JUSTIFY);
			setAlignmentLast(justifyLastLine ? TextAlign.JUSTIFY : TextAlign.LEFT);

			// capture block progression so we know whether glyph spacing will happen
			// along x or y axis.
			var bp:String = SelManager.textFlow.computedFormat.blockProgression;
			var line:TextLine;


			setTextJustify(TextJustify.INTER_WORD);

			if(lastLine)
			{
				line = SelManager.textFlow.flowComposer.findLineAtPosition(longWordTextLastPosition).getTextLine(true);
			}
			else
			{
				line = SelManager.textFlow.flowComposer.getLineAt(0).getTextLine(true);
			}


			var xPosInterWord:Array = [];

			// Collect the x coordinates for each glyph
			for ( var i:int = 0; i < line.atomCount; i++)
			{
				var r:Rectangle = line.getAtomBounds(i);
				xPosInterWord.push(Number(bp == BlockProgression.TB ? r.x : r.y));
			}

			setTextJustify(TextJustify.DISTRIBUTE);

			if(lastLine)
			{
				line = SelManager.textFlow.flowComposer.findLineAtPosition(longWordTextLastPosition).getTextLine(true);
			}
			else
			{
				line = SelManager.textFlow.flowComposer.getLineAt(0).getTextLine(true);
			}

			var xPosDistribute:Array = [];

			// Collect the x coordinates for each glyph
			for ( i = 0; i < line.atomCount; i++)
			{
				r = line.getAtomBounds(i);
				xPosDistribute.push(Number(bp == BlockProgression.TB ? r.x : r.y));
			}

			var foundDifferentSpacing:Boolean = false;
			for( i=0; i<xPosInterWord.length; ++i)
			{
				if(xPosInterWord[i] != xPosDistribute[i])
				{
					foundDifferentSpacing = true;
				}
			}

			assertTrue("Line length changed as a result of changing textJustify setting! ",
					xPosInterWord.length == xPosDistribute.length);

			if(lastLine && !justifyLastLine)
			{
				assertTrue("Letterspacing on/off moved glyphs on unjustified last line in paragraph!",
					!foundDifferentSpacing);
			}
			else
			{
				assertTrue("Letterspacing on/off did not move glyphs in justified text!",
						foundDifferentSpacing);
			}

		}

		/**
		 *
		 * Get a short selection and set the textJustify to DISTRIBUTE and
		 * check that it is set correctly.
		 */
		[Test]
		public function justifyDistributeTest():void
		{
			// Set the selection.
			var startIndx:int = 10;
			var endIndx:int = 20;
			SelManager.selectRange(startIndx,endIndx);
			// Set the alignment.
			setTextJustify(TextJustify.DISTRIBUTE);
			// Confirm the alignment was set.
			assertTrue("textJustify is not distribute - it's " + getTextJustify(),
						getTextJustify() == TextJustify.DISTRIBUTE);
		}

		private function setAlignment(attrValue:String):void
		{
			var pa:TextLayoutFormat = new TextLayoutFormat();
			pa.textAlign = attrValue;
			SelManager.applyParagraphFormat(pa);
		}

		private function getAlignment():String
		{
			var startOfPara:int = SelManager.anchorPosition;
			var endOfPara:int = SelManager.activePosition;
			var curAlign:Object = null;
			var i:int;

			for (i = startOfPara; i <= endOfPara; i++)
			{
				var para:ParagraphElement = SelManager.textFlow.findAbsoluteParagraph(i);
			    var paraAttr:ITextLayoutFormat = para.computedFormat;
				if (curAlign == null)
					curAlign = paraAttr.textAlign;
				else if (curAlign != String(paraAttr.textAlign))
				{
					curAlign = "Mixed";
					break;
				}
			}
			return String(curAlign);
		}

		private function setTextJustify(attrValue:String):void
		{
			var pa:TextLayoutFormat = new TextLayoutFormat();
			pa.textJustify = attrValue;
			SelManager.applyParagraphFormat(pa);
		}

		private function getTextJustify():String
		{
			var startOfPara:int = SelManager.anchorPosition;
			var endOfPara:int = SelManager.activePosition;
			var curJustify:Object = null;
			var i:int;

			for (i = startOfPara; i <= endOfPara; i++)
			{
				var para:ParagraphElement = SelManager.textFlow.findAbsoluteParagraph(i);
			    var paraAttr:ITextLayoutFormat = para.computedFormat;
				if (curJustify == null)
					curJustify = paraAttr.textJustify;
				else if (curJustify != String(paraAttr.textJustify))
				{
					curJustify = "Mixed";
					break;
				}
			}
			return String(curJustify);
		}

		private function setAlignmentLast(attrValue:String):void
		{
			var pa:TextLayoutFormat = new TextLayoutFormat();
			pa.textAlignLast = attrValue;
			SelManager.applyParagraphFormat(pa);
		}

		private function getAlignmentLast():String
		{
			var startOfPara:int = SelManager.anchorPosition;
			var endOfPara:int = SelManager.activePosition;
			var curAlign:Object = null;
			var i:int;

			for (i = startOfPara; i <= endOfPara; i++)
			{
				var para:ParagraphElement = SelManager.textFlow.findAbsoluteParagraph(i);
			    var paraAttr:ITextLayoutFormat = para.computedFormat;
				if (curAlign == null)
					curAlign = paraAttr.textAlignLast;
				else if (curAlign != String(paraAttr.textAlignLast))
				{
					curAlign = "Mixed";
					break;
				}
			}
			return String(curAlign);
		}

		/* ************************************************************** */
		/* Indent Tests */
		/* ************************************************************** */


		/**
		 * Set an indent of ten and check that it is set correctly.
		 */
		[Test]
		public function setIndentPositiveTest():void
		{
			setIndent(10);
			assertTrue("indent is not 10", getIndent(10));
		}

		/**
		 * Set an indent of negative ten and check that it is set correctly.
		 */
		[Test]
		public function setIndentNegativeTest():void
		{
			setIndent(-10);
			assertTrue("indent is not -10", getIndent(-10));
		}

		private function setIndent(amount:Number):void
		{
			var pa:TextLayoutFormat = new TextLayoutFormat();
			pa.textIndent = amount;
			SelManager.applyParagraphFormat(pa);
		}

		private function getIndent(amount:Number = -1):Boolean
		{
			var startOfPara:int = SelManager.anchorPosition;
			var endOfPara:int = SelManager.activePosition;
			var curIndent:Object =(amount == -1) ? null : Object(amount);
			var i:int;
			var success:Boolean = true;

			for (i = startOfPara; i <= endOfPara; i++)
			{
				var para:ParagraphElement = SelManager.textFlow.findAbsoluteParagraph(i);
			    var paraAttr:ITextLayoutFormat = para.format;

				if (curIndent == -1)
					curIndent = paraAttr.textIndent;
				else if (curIndent != paraAttr.textIndent)
				{

					success = false;
					break;
				}
			}
			return success;
		}

		/* ************************************************************** */
		/* Left Margin Tests */
		/* ************************************************************** */

		/**
		 * Set a left margin of ten and check that it is set correctly.
		 */
		[Test]
		public function setLeftMarginPositiveTest():void
		{
			setLeftMargin(10);
			assertTrue("margin is not 10", getLeftMargin(10));
		}

		/**
		 * Set a left margin of negative ten and check that it is set to zero
		 * (i.e. no negative left margins).
		 */
		[Test]
		public function setLeftMarginNegativeTest():void
		{
			setLeftMargin(-10,true);
			assertTrue("margin is not 0", getLeftMargin(0)); // set test value to 0 I don't think you can have a negative margin KJT
		}

		private var errorCount:int;
		private function myErrorHandler(p:Property,value:Object):void
		{
			errorCount++;
		}


		private function setLeftMargin(amount:Number,expectError:Boolean = false):void
		{
			var savedErrorHandler:Function = Property.errorHandler;
			errorCount = 0;
			Property.errorHandler = myErrorHandler;
			var pa:TextLayoutFormat = new TextLayoutFormat();
			pa.paragraphStartIndent = amount;
			Property.errorHandler = savedErrorHandler;

			if (expectError)
				assertTrue("expected error not received",errorCount == 1);
			else
				assertTrue("unexpected error received",errorCount == 0);

			if (!expectError)
				SelManager.applyParagraphFormat(pa);
		}

		private function getLeftMargin(amount:Number = -1):Boolean
		{
			var startOfPara:int = SelManager.anchorPosition;
			var endOfPara:int = SelManager.activePosition;
			var curAmount:Object = null;
			if (amount != -1)
				curAmount = Object(amount);
			var i:int;
			var success:Boolean = true;

			for (i = startOfPara; i <= endOfPara; i++)
			{
				var para:ParagraphElement = SelManager.textFlow.findAbsoluteParagraph(i);
			    var paraAttr:ITextLayoutFormat = para.computedFormat;
				if (curAmount == null)
					curAmount = paraAttr.paragraphStartIndent;
				else if (curAmount != paraAttr.paragraphStartIndent)
				{
					success = false;
					break;
				}
			}
			return success;
		}

		/* ************************************************************** */
		/* Right Margin Tests */
		/* ************************************************************** */


		/**
		 * Set a right margin of ten and check that it is set correctly.
		 */
		[Test]
		public function setRightMarginPositiveTest():void
		{
			setRightMargin(10);
			assertTrue("right margin is not 10", getRightMargin(10));
		}

		/**
		 * Set a right margin of negative ten and check that it is set to zero
		 * (i.e. no negative right margins).
		 */
		[Test]
		public function setRightMarginNegativeTest():void
		{
			setRightMargin(-10,true);

			assertTrue("right margin is not 0", getRightMargin(0)); // set test value to 0 I don't think you can have a negative margin KJT

		}

		private function setRightMargin(amount:Number,expectError:Boolean = false):void
		{
			var savedErrorHandler:Function = Property.errorHandler;
			errorCount = 0;
			Property.errorHandler = myErrorHandler;
			var pa:TextLayoutFormat = new TextLayoutFormat();
			pa.paragraphEndIndent = amount;
			Property.errorHandler = savedErrorHandler;

			if (expectError)
				assertTrue("expected error not received",errorCount == 1);
			else
				assertTrue("unexpected error received",errorCount == 0);

			if (!expectError)
				SelManager.applyParagraphFormat(pa);
		}

		private function getRightMargin(amount:Number = -1):Boolean
		{
			var startOfPara:int = SelManager.anchorPosition;
			var endOfPara:int = SelManager.activePosition;
			var curAmount:Object = null;
			if (amount != -1)
				curAmount = Object(amount);
			var i:int;
			var success:Boolean = true;

			for (i = startOfPara; i <= endOfPara; i++)
			{
				var para:ParagraphElement = SelManager.textFlow.findAbsoluteParagraph(i);
			    var paraAttr:ITextLayoutFormat = para.computedFormat;
				if (curAmount == null)
					curAmount = paraAttr.paragraphEndIndent;
				else if (curAmount != paraAttr.paragraphEndIndent)
				{

					success = false;
					break;
				}
			}
			return success;
		}

		/* ************************************************************** */
		/* Space Before Tests */
		/* ************************************************************** */

		/**
		 * Set space before value to twenty-five and check that it is set correctly.
		 */
		[Test]
		public function setSpaceBeforePositiveTest():void
		{
			setSpaceBefore(25);
			assertTrue("space before is not 25", getSpaceBefore(25));
		}

		/**
		 * Set space before value to negative fifty and check that it is zero
		 * (i.e. no negative space before values).
		 */
		[Test]
		public function setSpaceBeforeNegativeTest():void
		{
			setSpaceBefore(-50,true);
			assertTrue("space before is not 0", getSpaceBefore(0)); // set test value to 0 I don't think you can have a negative spaceBefore KJT

		}

		private function setSpaceBefore(spaceBeforeValue:Number,expectError:Boolean = false):void
		{
			var savedErrorHandler:Function = Property.errorHandler;
			errorCount = 0;
			Property.errorHandler = myErrorHandler;
			var pa:TextLayoutFormat = new TextLayoutFormat();
			pa.paragraphSpaceBefore = spaceBeforeValue;
			Property.errorHandler = savedErrorHandler;

			if (expectError)
				assertTrue("expected error not received",errorCount == 1);
			else
				assertTrue("unexpected error received",errorCount == 0);

			if (!expectError)
				SelManager.applyParagraphFormat(pa);
		}

		private function getSpaceBefore(amount:Number = -1):Boolean
		{
			var startOfPara:int = SelManager.anchorPosition;
			var endOfPara:int = SelManager.activePosition;
			var curAmount:Object = null;
			if (amount != -1)
				curAmount = Object(amount);
			var i:int;
			var success:Boolean = true;

			for (i = startOfPara; i <= endOfPara; i++)
			{
				var para:ParagraphElement = SelManager.textFlow.findAbsoluteParagraph(i);
			    var paraAttr:ITextLayoutFormat = para.computedFormat;
				if (curAmount == null)
					curAmount = paraAttr.paragraphSpaceBefore;
				else if (curAmount != paraAttr.paragraphSpaceBefore)
				{
					success = false;
					break;
				}
			}
			return success;
		}

		/* ************************************************************** */
		/* Space After Tests */
		/* ************************************************************** */

		/**
		 * Set space after value to twenty-five and check that it is set correctly.
		 */
		[Test]
		public function setSpaceAfterPositiveTest():void
		{
			setSpaceAfter(25);
			assertTrue("space after is not 25", getSpaceAfter(25));
		}

		/**
		 * Set space after value to negative fifty and check that it is zero
		 * (i.e. no negative space after values).
		 */
		[Test]
		[Ignore]
		public function setSpaceAfterNegativeTest():void
		{
			setSpaceAfter(-50);
			assertTrue("space before is not 0", getSpaceAfter(0)); // set test value to 0 I don't think you can have a negative spaceAfter KJT

		}

		private function setSpaceAfter(spaceAfterValue:Number):void
		{
			var pa:TextLayoutFormat = new TextLayoutFormat();
			pa.paragraphSpaceAfter = spaceAfterValue;
			SelManager.applyParagraphFormat(pa);
		}

		private function getSpaceAfter(amount:Number = -1):Boolean
		{
			var startOfPara:int = SelManager.anchorPosition;
			var endOfPara:int = SelManager.activePosition;
			var curAmount:Object = null;
			if (amount != -1)
				curAmount = Object(amount);
			var i:int;
			var success:Boolean = true;

			for (i = startOfPara; i <= endOfPara; i++)
			{
				var para:ParagraphElement = SelManager.textFlow.findAbsoluteParagraph(i);
			    var paraAttr:ITextLayoutFormat = para.computedFormat;
				if (curAmount == null)
					curAmount = paraAttr.paragraphSpaceAfter;
				else if (curAmount != paraAttr.paragraphSpaceAfter)
				{
					success = false;
					break;
				}
			}
			return success;
		}

		[Test]
		public function joinParagraphsTest():void
		{
			var flow1:FlowElement;
			var flow2:FlowElement;
			//This is the length to the end of the first text.
			var length:int = 0;

			//Look for two back to back paragraphs.
			for(var i:int = 0; i < TestFrame.rootElement.numChildren-1; i++){
				flow1 = TestFrame.rootElement.getChildAt(i);
				flow2 = TestFrame.rootElement.getChildAt(i+1);

				length = length + flow1.textLength;

				if(flow1 is ParagraphElement && flow2 is ParagraphElement) break;
			}

			var para1:ParagraphElement = flow1 as ParagraphElement;
			var para2:ParagraphElement = flow2 as ParagraphElement;

			var attrib1:ITextLayoutFormat = para1.computedFormat;
			var attrib2:ITextLayoutFormat = para2.computedFormat;

			if(!Property.equalAllHelper(TextLayoutFormat.description,attrib1,attrib2)){
				for each (var prop:Property in TextLayoutFormat.description){
					var name:String = prop.name;

					para2[name] = attrib1[name].valueOf();
				}
			}

			attrib2 = para2.computedFormat;

			assertTrue("attributes have changed",
				Property.equalAllHelper(
					TextLayoutFormat.description,
					attrib1,
					attrib2
				)
			);

			if(attrib1.textAlign == TextAlign.JUSTIFY){
				para1.textAlign = TextAlign.CENTER;
			}else {
				para1.textAlign = TextAlign.JUSTIFY;
			}

			attrib1 = para1.computedFormat;
			attrib2 = para2.computedFormat;

			assertTrue("attributes did not change",
				!Property.equalAllHelper(
					TextLayoutFormat.description,
					attrib1,
					attrib2
				)
			);

			SelManager.selectRange(length-1,length-1);
			var origLen1:Number = para1.textLength;
			var origLen2:Number = para2.textLength;

			var event:KeyboardEvent = new KeyboardEvent(KeyboardEvent.KEY_DOWN, true, false, 127, 46);
			TestFrame.container["dispatchEvent"](event);
			TestFrame.textFlow.flowComposer.compose();

			var newLen1:Number = para1.textLength;
			var newLen2:Number = para2.textLength;

			assertTrue("paragraphs incorrectly joined",
						newLen1 == (origLen1+origLen2-1) &&
						newLen2 == 0 );

			// Make sure old attributes are preserved after undo

			SelManager.undo();

			attrib1 = para1.computedFormat;
			attrib2 = para2.computedFormat;

			assertTrue("attributes changed after an undo",
				!Property.equalAllHelper(
					TextLayoutFormat.description,
					attrib1,
					attrib2
				)
			);
		}

		/**
		 * Set the size of the text and autoleading, then change them and make sure that the
		 * leading is the correct value.
		 */
		[Test]
		public function autoLeadingTest():void
		{
			const acceptableErrorAmt:Number = .02;

			SelManager.selectAll();

//			var para:ParagraphElement = SelManager.textFlow.findAbsoluteParagraph(0);
//			var attribs:IParagraphFormat = para.computedFormat;
//			var initALP:Number = attribs.autoLeadingPercent as Number;

			var initSize:Number = 10;
			var ca:TextLayoutFormat = new TextLayoutFormat();
			ca.fontSize = initSize;
			var initALP:Number = 130;
			ca.lineHeight = initALP.toString() + '%';
			SelManager.applyLeafFormat(ca);

			SelManager.textFlow.flowComposer.compose();

			var line0:TextFlowLine = SelManager.textFlow.flowComposer.getLineAt(0) as TextFlowLine;
			var line1:TextFlowLine = SelManager.textFlow.flowComposer.getLineAt(1) as TextFlowLine;

			var initLead:Number;

			if ( SelManager.textFlow.computedFormat.blockProgression == BlockProgression.RL )
			{
				initLead = Math.abs(line1.x - line0.x);
			}
			else
			{
				initLead = Math.abs(line1.y - line0.y);
			}

			assertTrue( "Leading is not correct value", Math.abs(((initALP/100) * initSize) - initLead) <= acceptableErrorAmt);

			var finalALP:Number = initALP + 30;
			var finalSize:Number = initSize + 10;

			var ca2:TextLayoutFormat = new TextLayoutFormat();
			ca2.lineHeight = finalALP.toString() + '%';
			SelManager.applyLeafFormat(ca2);

			SelManager.textFlow.flowComposer.compose();

			line0 = SelManager.textFlow.flowComposer.getLineAt(0) as TextFlowLine;
			line1 = SelManager.textFlow.flowComposer.getLineAt(1) as TextFlowLine;

			var middleLead:Number;

			if ( SelManager.textFlow.computedFormat.blockProgression == BlockProgression.RL )
			{
				middleLead = Math.abs(line1.x - line0.x);
			}
			else
			{
				middleLead = Math.abs(line1.y - line0.y);
			}

			assertTrue( "Leading is not correct value", Math.abs(((finalALP/100) * initSize) - middleLead) <= acceptableErrorAmt);

			ca = new TextLayoutFormat();
			ca.fontSize = finalSize;
			SelManager.applyLeafFormat(ca);

			SelManager.textFlow.flowComposer.compose();

			line0 = SelManager.textFlow.flowComposer.getLineAt(0) as TextFlowLine;
			line1 = SelManager.textFlow.flowComposer.getLineAt(1) as TextFlowLine;

			var finalLead:Number;

			if ( SelManager.textFlow.computedFormat.blockProgression == BlockProgression.RL )
			{
				finalLead = Math.abs(line1.x - line0.x);
			}
			else
			{
				finalLead = Math.abs(line1.y - line0.y);
			}

			assertTrue( "Leading is not correct value", Math.abs(((finalALP/100) * finalSize) - finalLead) <= acceptableErrorAmt);
		}

		/**
		 * Create an empty paragraph and set its attributes. Then insert text and see if
		 * the paragraph still has its attributes.
		 */
		[Test]
		public function paragraphAttributeRetentionTest():void
		{
			SelManager.selectRange(0,0);

			var returnevent:KeyboardEvent =
				new KeyboardEvent(KeyboardEvent.KEY_DOWN, true, false, 13);
			TestFrame.container["dispatchEvent"](returnevent);


			SelManager.selectRange(0,0);

			var para:ParagraphElement = SelManager.textFlow.findAbsoluteParagraph(0);
			var attribs:ITextLayoutFormat = para.computedFormat;
			var initTextIndent:Number = Number(attribs.textIndent);

			var pa:TextLayoutFormat = new TextLayoutFormat();
			pa.textIndent = initTextIndent + 30;
			SelManager.applyParagraphFormat(pa);

			SelManager.insertText("I should be indented 30!");

			para = SelManager.textFlow.findAbsoluteParagraph(0);
			attribs = para.computedFormat;

			assertTrue(attribs.textIndent == initTextIndent + 30);
		}

		/**
		 * Create a paragraph attributes object, set all the number values to a limit (
		 * low limit if the attribute is at the high limit, high limit if it's anywhere
		 * else), then create a new attributes object based on it and reverse the first
		 * attribute. Then perform TextLayoutFormat.removeMatching and verify the only
		 * property left is the one you set to a different value, and ensure no other
		 * values remain.
		 */
		[Test]
		public function paragraphAttributeRemovalTest():void
		{
			var desc:Object = TextLayoutFormat.description;

			var pa:TextLayoutFormat = new TextLayoutFormat();
			var handler:NumberPropertyHandler;

			var good:Array = [];
			for each (var prop:Property in desc){
				handler = prop.findHandler(NumberPropertyHandler) as NumberPropertyHandler;
				if (handler)
				{
					var name:String = prop.name;
					good.push(name);

					if(pa[name] == handler.maxValue){
						pa[name] = handler.minValue;
					}else{
						pa[name] = handler.maxValue;
					}
				}
			}

			var antiPa:TextLayoutFormat = new TextLayoutFormat(pa);

			var anti:String = "";
			for each (name in good)
			{
				handler = (desc[name].findHandler(NumberPropertyHandler) as NumberPropertyHandler);
				if(antiPa[name] == handler.minValue){
					antiPa[name] = handler.maxValue;
					anti = name;
					break;
				}else{
					antiPa[name] = handler.minValue;
					anti = name;
					break;
				}
			}

			antiPa.removeMatching(pa);
			for each (name in good){
				if(name == anti){
					assertTrue("Attribute to be retained was nulled!", antiPa[name] != null);
					assertTrue("Attribute to be retained was set to previous value!", antiPa[name] != pa[name]);
				}else{
					assertTrue("Attribute to be removed was retained!", antiPa[name] == null);
				}
			}
		}

		/**
		 * Create an empty paragraph at the end of a text flow and see if the
		 * character attributes from the previous paragraph have been applied to it.
		 */
		[Test]
		public function characterAttributeRetentionTest():void
		{
			var length:int = SelManager.textFlow.textLength - 1;

			var lastLeaf:FlowLeafElement = SelManager.textFlow.findLeaf(length);
			var lastCharAttr:ITextLayoutFormat = lastLeaf.computedFormat;

			SelManager.selectRange(length,length);

			var returnevent:KeyboardEvent =
				new KeyboardEvent(KeyboardEvent.KEY_DOWN, true, false, 13);
			TestFrame.container["dispatchEvent"](returnevent);

			SelManager.flushPendingOperations();

			length = SelManager.textFlow.textLength - 1;
			SelManager.selectRange(length,length);

			var newLeaf:FlowLeafElement = SelManager.textFlow.findLeaf(length);
			var newCharAttr:ITextLayoutFormat = newLeaf.computedFormat;
		}

		private function checkTabstopFormat (obj:Object, type:String, position:Number, alignmentToken:String):Boolean
		{
			var tabStop:TabStopFormat = obj as TabStopFormat;
			if (!tabStop)
				return false;

			return tabStop.alignment == type && tabStop.position == position && (tabStop.alignment == TabAlignment.DECIMAL ?  tabStop.decimalAlignmentToken == alignmentToken : true);
		}

		/**
		 * Validate parsing of string-based tabStops syntax
		 */
		[Test]
		public function tabStopsStringFormTest():void
		{
			var pa:TextLayoutFormat = new TextLayoutFormat();
			pa.tabStops = " 200 s100    C400 d350 D700|::    e800  d850|\\  d900|\\\\     ";

			var tabStopsRetval:Object = pa.tabStops;
			assertTrue("tabStops getter returned null", tabStopsRetval);

			var tabStops:Array = tabStopsRetval as Array;
			assertTrue("tabStops getter did not return an array", tabStops);

			var parseSuccess:Boolean = (tabStops.length == 8) &&
				 checkTabstopFormat (tabStops[0], TabAlignment.START, 100, null) &&
				 checkTabstopFormat (tabStops[1], TabAlignment.START, 200, null) &&
				 checkTabstopFormat (tabStops[2], TabAlignment.DECIMAL, 350, ".") &&
				 checkTabstopFormat (tabStops[3], TabAlignment.CENTER, 400, null) &&
				 checkTabstopFormat (tabStops[4], TabAlignment.DECIMAL, 700, "::") &&
				 checkTabstopFormat (tabStops[5], TabAlignment.END, 800, null) &&
				 checkTabstopFormat (tabStops[5], TabAlignment.DECIMAL, 850, " ") &&
				 checkTabstopFormat (tabStops[5], TabAlignment.DECIMAL, 900, "\\");

			assertTrue(parseSuccess, "string form of tabStops incorrectly parsed");
		}

		/* this is for testing a bug.  Bug description: Launch Flow.wsf, Select a chunk of text in the second paragraph, then
		   choose a visible background color (pink, for example), in Advanced Character, choose a Background Alpha around 20%,
		   deselect the text and note how light it is. Click in the first paragraph and start typing.  Note that with each keystroke
		   the background color appears darker.
		*/
		[Test(dataProvider=backgroundcolorchangeTestDp)]
		public function backgroundcolorchangeTest(testCaseVo:TestCaseVo):void
		{
			TestData.fileName = testCaseVo.fileName;
			setUpTest();

			var insertPoint:int = 14;
    		var tlf:TextLayoutFormat = new TextLayoutFormat();
   			tlf.backgroundColor = 0xFF00FF;
   			tlf.backgroundAlpha = .2;
   			tlf.fontSize = 40;

    		SelManager.selectRange(0,0);
   			SelManager.insertText("This is a test" +
               "            a");
   		    SelManager.selectRange(insertPoint, insertPoint);
    		SelManager.splitParagraph();
  		    var tf:TextFlow = SelManager.textFlow;
        	var p1:ParagraphElement = tf.getChildAt(0) as ParagraphElement;
        	var p2:ParagraphElement = tf.getChildAt(1) as ParagraphElement;
        	var p1start:int = p1.getAbsoluteStart();
        	var p1end:int = p1.textLength - 1;
       		var p2start:int = p2.getAbsoluteStart();
        	var p2end:int = p2start + p2.textLength - 1;

        	SelManager.selectRange(p2start, p2end);
        	SelManager.applyLeafFormat(tlf);
        	SelManager.selectRange(0,0);

       		// get the rect where the first character of the second line is  displayed
        	var testLine:TextLine =  SelManager.textFlow.flowComposer.getLineAt(1).getTextLine();
        	var characterBounds:Rectangle = testLine.getAtomBounds(0);
    		characterBounds.offset (testLine.x, testLine.y);
        	var testRect:Rectangle = new Rectangle;
        	testRect.height = characterBounds.height;
        	testRect.width = characterBounds.width;
        	var containerMatrix:Matrix = new Matrix (1,0,0,1,-characterBounds.x, -characterBounds.y);

     		//save bitmap of that rect before adding text to para 1
    		var beforeBitmapData:BitmapData = new  BitmapData(testRect.width,testRect.height);
    		beforeBitmapData.draw(TestFrame.container as IBitmapDrawable, containerMatrix, null, null, testRect);
        	var beforeBitmap:Bitmap = new Bitmap (beforeBitmapData);

    		//append some text to paragraph 1
   			SelManager.selectRange(p1end, p1end);
   			SelManager.insertText("AAA");
   			TestFrame.flowComposer.updateAllControllers();

   			//save bitmap of paragraph 2 after append text to paragraph 1
    		var afterBitmapData:BitmapData = new  BitmapData(testRect.width,testRect.height);
    		afterBitmapData.draw(TestFrame.container as IBitmapDrawable,containerMatrix, null, null, testRect);
        	var afterBitmap:Bitmap = new Bitmap(afterBitmapData);

    		// This will do the bitmap compare of the two bitmaps.
    		afterBitmap.bitmapData.draw(beforeBitmap, null, null, "difference");
    		var bounds:Rectangle = new Rectangle(0, 0, afterBitmap.width,afterBitmap.height);
    		var diffPixels:ByteArray = afterBitmap.bitmapData.getPixels(bounds);
    		diffPixels.position = 0;
    		var pixelCount:Number = diffPixels.bytesAvailable;
    		var diffCount:Number = 0;
   			while (diffPixels.bytesAvailable > 0)
    		{
     			if (diffPixels.readByte() > 0)
     			{
      				diffCount ++;
     			}
    		}

    		var diff:Number = diffCount/pixelCount*100;

   			assertTrue("Background color has been changed after appending text  to paragraph 1." + " The diff is "+
    				diff + " And the diffTolerance is " + diffTolerance, diff < diffTolerance);

		}

		/* this is for testing the bug 2371905.  Final Empty Paragraph Shows No Selection When Block Selected
		*/
		[Test(dataProvider=backgroundcolorchangeTestDp)]
		public function FinalEmptyParaTest(testCaseVo:TestCaseVo):void
		{
			TestData.fileName = testCaseVo.fileName;
			setUpTest();

			var insertPoint:int = 14;

    		SelManager.selectRange(0,0);
   			SelManager.insertText("This is a test" + "            ");
   		    SelManager.selectRange(insertPoint, insertPoint);
    		SelManager.splitParagraph();
  		    var tf:TextFlow = SelManager.textFlow;
        	var p1:ParagraphElement = tf.getChildAt(0) as ParagraphElement;
        	var p2:ParagraphElement = tf.getChildAt(1) as ParagraphElement;
        	var p1start:int = p1.getAbsoluteStart();
        	var p1end:int = p1.textLength - 1;
       		var p2start:int = p2.getAbsoluteStart();
        	var p2end:int = p2start + p2.textLength - 1;

        	SelManager.selectAll();

        	var absoluteEnd:int = SelManager.absoluteEnd;

			assertTrue("Final Empty paragragh has not been selected" + " final empty paragraph end at index " + p2end +
			" and the real absolute End index is: " + absoluteEnd, p2end == absoluteEnd);
		}
	}
}
