////////////////////////////////////////////////////////////////////////////////
//
//  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.TestSuiteExtended;
	import UnitTest.ExtendedClasses.VellumTestCase;
	import UnitTest.Fixtures.TestConfig;
	import UnitTest.Validation.*;
	
	import flash.display.DisplayObjectContainer;
	import flash.display.Shape;
	import flash.events.*;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import flash.text.engine.TextLine;
	
	import flashx.textLayout.compose.IFlowComposer;
	import flashx.textLayout.compose.TextFlowLine;
	import flashx.textLayout.container.ContainerController;
	import flashx.textLayout.container.ScrollPolicy;
	import flashx.textLayout.edit.IEditManager;
	import flashx.textLayout.edit.SelectionManager;
	import flashx.textLayout.edit.SelectionState;
	import flashx.textLayout.edit.TextScrap;
	import flashx.textLayout.elements.*;
	import flashx.textLayout.events.CompositionCompleteEvent;
	import flashx.textLayout.events.DamageEvent;
	import flashx.textLayout.events.FlowElementMouseEvent;
	import flashx.textLayout.events.FlowOperationEvent;
	import flashx.textLayout.events.ScrollEvent;
	import flashx.textLayout.events.ScrollEventDirection;
	import flashx.textLayout.events.SelectionEvent;
	import flashx.textLayout.events.StatusChangeEvent;
	import flashx.textLayout.events.TextLayoutEvent;
	import flashx.textLayout.events.UpdateCompleteEvent;
	import flashx.textLayout.formats.BlockProgression;
	import flashx.textLayout.formats.TextAlign;
	import flashx.textLayout.formats.TextLayoutFormat;
	import flashx.textLayout.operations.FlowElementOperation;
	import flashx.textLayout.operations.FlowOperation;
	import flashx.textLayout.operations.InsertInlineGraphicOperation;
	import flashx.textLayout.operations.RedoOperation;
	import flashx.textLayout.operations.UndoOperation;
	import flashx.textLayout.tlf_internal;
	import flashx.textLayout.utils.GeometryUtil;
	
	import mx.controls.scrollClasses.ScrollBar;
	import mx.utils.LoaderUtil;

	use namespace tlf_internal;

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

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

		public static function suiteFromXML(testListXML:XML, testConfig:TestConfig, ts:TestSuiteExtended):void
 		{
 			var testCaseClass:Class = AllEventTest;
 			VellumTestCase.suiteFromXML(testCaseClass, testListXML, testConfig, ts);
 		}

    	private function beginSelectionEventValidation(target:IEventDispatcher, eventCount:int, validater:Function):void
    	{
   			target.addEventListener(SelectionEvent.SELECTION_CHANGE, validater);
    	}

    	//SelectionEvent Test Cases
    	public function selectionEventTest():void
    	{
   			metaData.productArea = "Editing";

   			this.SelManager.selectRange(0,0);

			var textFlow:TextFlow = this.SelManager.textFlow;
			var endIdx:int = 200;
			var startIdx:int = 100;

			var theRects:Array = GeometryUtil.getHighlightBounds(new TextRange(textFlow, startIdx, endIdx));
			for each(var lineRectPair:Object in theRects)
			{
				var theLine:TextLine = lineRectPair.textLine as TextLine;
				var rect:Rectangle = lineRectPair.rect as Rectangle;
				var tfl:TextFlowLine = theLine.userData as TextFlowLine;
				assertTrue( "userData on a textLine should be a TextFlowLine!", tfl);

				var parentObj:DisplayObjectContainer = theLine.parent;
				var selObj:Shape = new Shape();

				var globalStart:Point = new Point(rect.x, rect.y);

				//first "click" inside the bounds of the rect and make sure we have a point within the selection range:
				var index:int = SelectionManager.tlf_internal::computeSelectionIndex(textFlow, theLine, null, rect.x + (rect.width/2), rect.y + (rect.height/2));

				//validate using a calculated index.  If this is a partial line selection, then using the abs start and end isn't valid.
				var checkStart:int = tfl.absoluteStart >= startIdx ? tfl.absoluteStart : startIdx;
				var checkEnd:int = (tfl.absoluteStart + tfl.textLength) <= endIdx ? (tfl.absoluteStart + tfl.textLength) : endIdx;

				//validate
				assertTrue( "the computed index derived from the selection shape must be within the line!", checkStart <= index && checkEnd >= index);
			}

   			// Select All
   			var validator:SelectionEventValidator = new SelectionEventValidator(TestFrame.textFlow,
   				new SelectionEvent(SelectionEvent.SELECTION_CHANGE, false, false, new SelectionState(TestFrame.textFlow, 0, TestFrame.textFlow.textLength - 1)));
			SelManager.selectAll();
   			assertTrue("Expected selection event showing entire flow selected", validator.validate(1));

			// Select range
			validator.reset(new SelectionEvent(SelectionEvent.SELECTION_CHANGE, false, false, new SelectionState(TestFrame.textFlow, 10, 100)));
     		SelManager.selectRange(10, 100);
     		SelManager.refreshSelection();
   			assertTrue("Expected selection event showing range selected", validator.validate(1));

			// Apply format -- expects selection changed on selected area b/c the contents changed
			var format:TextLayoutFormat = new TextLayoutFormat();
			format.fontSize = 48;
   			validator.reset();
			(SelManager as IEditManager).applyLeafFormat(format);
   			assertTrue("Expected selection event after formatting applied", validator.validate(1));

			// Insert text -- expects selection changed on selected area b/c the contents changed
 			const textToInsert:String = "FOO";
 			validator.reset(new SelectionEvent(SelectionEvent.SELECTION_CHANGE, false, false,
 				new SelectionState(TestFrame.textFlow, 20 + textToInsert.length, 20 + textToInsert.length)));
 			SelManager.selectRange(20, 20);
			(SelManager as IEditManager).insertText("FOO");
			SelManager.flushPendingOperations();  // force insert to happen right away
   			assertTrue("Expected selection event after text insertion", validator.validate(1));

			// Change select range - test that client code can change the selection from within a selection event handler
			textFlow.addEventListener(SelectionEvent.SELECTION_CHANGE, changeSelectionHandler);
			SelManager.selectRange(10, 100);
			SelManager.refreshSelection();
			assertTrue("Expected entire flow selected", SelManager.absoluteStart == 0 && SelManager.absoluteEnd == textFlow.textLength - 1);
			
			// Test selection by mouse. We should get one and only one event from this.
			SelManager.selectRange(10, 11);
			theRects = GeometryUtil.getHighlightBounds(new TextRange(textFlow, SelManager.absoluteStart, SelManager.absoluteEnd));
			theLine = theRects[0].textLine as TextLine;
			rect = theRects[0].rect as Rectangle;
			tfl = theLine.userData as TextFlowLine;
			var mouseEvent:MouseEvent = new MouseEvent(MouseEvent.MOUSE_DOWN, true, true, rect.x, rect.y, theLine, false, false, false, false);
			validator.reset(new SelectionEvent(SelectionEvent.SELECTION_CHANGE, false, false,
				new SelectionState(TestFrame.textFlow, 10, 10)));
			theLine.dispatchEvent(mouseEvent);
			assertTrue("Expected single selection event after mouse click", validator.validate(1));
		}

		private function changeSelectionHandler(event:SelectionEvent):void
		{
			var textFlow:TextFlow = event.selectionState.textFlow;
			textFlow.removeEventListener(SelectionEvent.SELECTION_CHANGE, changeSelectionHandler);
			textFlow.interactionManager.selectRange(0, textFlow.textLength);
		}

   		// DamageEvent Test Cases
   		public function damageEventTest():void
   		{
   			//Change Color Test
   			var selectionBegin:int = 20;
    		var selectionEnd:int = 400;
   			SelManager.selectRange(selectionBegin,selectionEnd);
   			var validator:DamageEventValidator = new DamageEventValidator(TestFrame.textFlow,
   				new DamageEvent(DamageEvent.DAMAGE, false, false, null, SelManager.absoluteStart, SelManager.absoluteEnd-SelManager.absoluteStart));
   			const fontColor:int = 0xFF0000;
			var ca:TextLayoutFormat = new TextLayoutFormat();

			ca.color = fontColor;
			SelManager.applyLeafFormat(ca);
			SelManager.flushPendingOperations();
   			assertTrue("Expected damage event showing after color change",validator.validate(1));

   			//Delete Text Test
   			validator.reset(new DamageEvent(DamageEvent.DAMAGE, false, false, null, SelManager.absoluteStart, SelManager.absoluteEnd-SelManager.absoluteStart));
   			SelManager.cutTextScrap(SelManager.getSelectionState());
   			SelManager.flushPendingOperations();
   			assertTrue("Expected damage event showing after text deletion",validator.validate(1));

   			//Delete Character Test
   			SelManager.selectRange(90,91);
   			validator.reset(new DamageEvent(DamageEvent.DAMAGE, false, false, null, SelManager.absoluteStart, SelManager.absoluteEnd-SelManager.absoluteStart));
   			SelManager.cutTextScrap(SelManager.getSelectionState());
   			SelManager.flushPendingOperations();
   			assertTrue("Expected damage event showing after character deletion",validator.validate(1));

   			//Change Geometry Test
   			validator.reset(new DamageEvent(DamageEvent.DAMAGE, false, false, TestFrame.textFlow, 0, TestFrame.textFlow.textLength));
   			TestFrame.setCompositionSize(500,500);
			TestFrame.textFlow.flowComposer.updateAllControllers();
			assertTrue("Expected damage event showing after Geometry change",validator.validate(1));

			//Change Block Progression Test
			validator.reset(new DamageEvent(DamageEvent.DAMAGE, false, false, TestFrame.textFlow, 0, TestFrame.textFlow.textLength));
   			TestFrame.textFlow.blockProgression = "rl";
			TestFrame.textFlow.flowComposer.updateAllControllers();
			assertTrue("Expected damage event showing after Block Progression change",validator.validate(1));

			//Change Font Size Test
			validator.reset(new DamageEvent(DamageEvent.DAMAGE, false, false, TestFrame.textFlow, 0, TestFrame.textFlow.textLength));
			TestFrame.textFlow.fontSize = 32;
			TestFrame.textFlow.flowComposer.updateAllControllers();
			assertTrue("Expected DamageEvent showing after Font Size change",validator.validate(1));
   		}

   		public function statusChangeEventTest():void
   		{
			metaData.productArea = "Editing";

			//Insert Picture Test
   			var src:String = LoaderUtil.createAbsoluteURL(baseURL,"../../test/testFiles/assets/leaves.jpg");
   			var element:InlineGraphicElement = new InlineGraphicElement();
   			element.source = src;
   			element.width = 30;
   			element.height = 30;
   			var validator:StatusChangeEventValidator = new StatusChangeEventValidator(TestFrame.textFlow,
   				new StatusChangeEvent(StatusChangeEvent.INLINE_GRAPHIC_STATUS_CHANGE, false, false, element, "loading", null));

   			var width:int = 30;
	  		var height:int = 30;
	  		var selectionBegin:int = 10;
			var selectionEnd:int = 10;
    		SelManager.selectRange(selectionBegin, selectionEnd);
	  		SelManager.insertInlineGraphic(src,width,height);
	  		SelManager.flushPendingOperations();

	  		assertTrue("Expected StatusChangeEvent showing after picture insertion",validator.validate(1));
   		}

		public function FlowOperationEventTest():void
		{
			metaData.productArea = "Editing";

			var src:String = LoaderUtil.createAbsoluteURL(baseURL,"../../test/testFiles/assets/leaves.jpg");
	  		var width:int = 30;
	  		var height:int = 30;
			var selectionBegin:int = 10;
			var selectionEnd:int = 10;
    		SelManager.selectRange(selectionBegin, selectionEnd);
			var operation:InsertInlineGraphicOperation = new InsertInlineGraphicOperation(SelManager.getSelectionState(),
				src, width, height,"none");
			var beginValidator:FlowOperationEventValidator = new FlowOperationEventValidator(TestFrame.textFlow,
				new FlowOperationEvent(FlowOperationEvent.FLOW_OPERATION_BEGIN, false, false, operation, 0, null));
			var endValidator:FlowOperationEventValidator = new FlowOperationEventValidator(TestFrame.textFlow,
				new FlowOperationEvent(FlowOperationEvent.FLOW_OPERATION_END, false, false, operation, 0, null));
			var completeValidator:FlowOperationEventValidator = new FlowOperationEventValidator(TestFrame.textFlow,
				new FlowOperationEvent(FlowOperationEvent.FLOW_OPERATION_COMPLETE, false, false, operation, 0, null));
			var compositionValidator:CompositionCompleteEventValidator = new CompositionCompleteEventValidator(TestFrame.textFlow,
				new CompositionCompleteEvent(CompositionCompleteEvent.COMPOSITION_COMPLETE, false, false, TestFrame.textFlow, 0, TestFrame.textFlow.textLength+1));
			SelManager.insertInlineGraphic(src,width,height);
	  		assertTrue("Expected FlowOperationBeginEvent during picture insertion", beginValidator.validate(1));
			assertTrue("Expected FlowOperationEndEvent during picture insertion", endValidator.validate(1));
			assertTrue("Expected FlowOperationCompleteEvent during picture insertion", completeValidator.validate(1));
			assertTrue("Expected CompositionCompleEvent during picture insertion", compositionValidator.validate(1));

			// Check undo
			var pseudoUndoOperation:UndoOperation = new UndoOperation(operation);
			beginValidator.reset(new FlowOperationEvent(FlowOperationEvent.FLOW_OPERATION_BEGIN, false, false, pseudoUndoOperation, 0, null));
			endValidator.reset(new FlowOperationEvent(FlowOperationEvent.FLOW_OPERATION_END, false, false, pseudoUndoOperation, 0, null));
			completeValidator.reset(new FlowOperationEvent(FlowOperationEvent.FLOW_OPERATION_COMPLETE, false, false, pseudoUndoOperation, 0, null));

			SelManager.undo();
			
			assertTrue("Expected FlowOperationBeginEvent during undo picture insertion", beginValidator.validate(1));
			assertTrue("Pseudo undo event should have been broadcast", FlowOperationEvent(beginValidator.lastEvent).operation is UndoOperation);
			assertTrue("Expected FlowOperationEndEvent during undo picture insertion", endValidator.validate(1));
			assertTrue("Pseudo undo event should have been broadcast", FlowOperationEvent(endValidator.lastEvent).operation is UndoOperation);
			assertTrue("Expected FlowOperationCompleteEvent undo during picture insertion", completeValidator.validate(1));
			assertTrue("Pseudo undo event should have been broadcast", FlowOperationEvent(completeValidator.lastEvent).operation is UndoOperation);

			// Check redo
			var pseudoRedoOperation:RedoOperation = new RedoOperation(operation);
			beginValidator.reset(new FlowOperationEvent(FlowOperationEvent.FLOW_OPERATION_BEGIN, false, false, pseudoRedoOperation, 0, null));
			endValidator.reset(new FlowOperationEvent(FlowOperationEvent.FLOW_OPERATION_END, false, false, pseudoRedoOperation, 0, null));
			completeValidator.reset(new FlowOperationEvent(FlowOperationEvent.FLOW_OPERATION_COMPLETE, false, false, pseudoRedoOperation, 0, null));

			SelManager.redo();
			
			assertTrue("Expected FlowOperationBeginEvent during redo picture insertion", beginValidator.validate(1));
			assertTrue("Pseudo redo event should have been broadcast", FlowOperationEvent(beginValidator.lastEvent).operation is RedoOperation);
			assertTrue("Expected FlowOperationEndEvent during redo picture insertion", endValidator.validate(1));
			assertTrue("Pseudo redo event should have been broadcast", FlowOperationEvent(endValidator.lastEvent).operation is RedoOperation);
			assertTrue("Expected FlowOperationCompleteEvent redo during picture insertion", completeValidator.validate(1));
			assertTrue("Pseudo redo event should have been broadcast", FlowOperationEvent(completeValidator.lastEvent).operation is RedoOperation);
			
		}

		public function FlowCompositeOperationEventTest():void
		{
			metaData.productArea = "Editing";

			var beginValidator:FlowOperationEventValidator = new FlowOperationEventValidator(TestFrame.textFlow,
				new FlowOperationEvent(FlowOperationEvent.FLOW_OPERATION_BEGIN, false, false, new FlowOperation(TestFrame.textFlow), 1, null));
			var endValidator:FlowOperationEventValidator = new FlowOperationEventValidator(TestFrame.textFlow,
				new FlowOperationEvent(FlowOperationEvent.FLOW_OPERATION_END, false, false, new FlowOperation(TestFrame.textFlow), 1, null));
			var completeValidator:FlowOperationEventValidator = new FlowOperationEventValidator(TestFrame.textFlow,
				new FlowOperationEvent(FlowOperationEvent.FLOW_OPERATION_COMPLETE, false, false, new FlowOperation(TestFrame.textFlow), 0, null));
			var compositionValidator:CompositionCompleteEventValidator = new CompositionCompleteEventValidator(TestFrame.textFlow,
				new CompositionCompleteEvent(CompositionCompleteEvent.COMPOSITION_COMPLETE, false, false, TestFrame.textFlow, 0, TestFrame.textFlow.textLength));

			SelManager.selectAll();
			SelManager.beginCompositeOperation();
			var leafFormat:TextLayoutFormat = new TextLayoutFormat();
			leafFormat.fontSize = 18;
			SelManager.applyLeafFormat(leafFormat);
			var paraFormat:TextLayoutFormat = new TextLayoutFormat();
			paraFormat.textAlign = TextAlign.CENTER;
			SelManager.applyParagraphFormat(paraFormat);
			SelManager.endCompositeOperation();

			assertTrue("Expected FlowOperationBeginEvent during composite operation", beginValidator.validate(2));
			assertTrue("Expected FlowOperationEndEvent during composite operation", endValidator.validate(2));
			assertTrue("Expected FlowOperationCompleteEvent during composite operation", completeValidator.validate(1));
			assertTrue("Expected CompositionCompleEvent during composite operation", compositionValidator.validate(1));
		}
		public function CompositionCompleteEventTest():void
		{
			var validator:CompositionCompleteEventValidator;
			var scroll:ScrollBar = new ScrollBar();
			var textHeight:int = Math.ceil(TestFrame.getContentBounds().height);
    		var textWidth:int = Math.ceil(TestFrame.getContentBounds().width);

			if (TestFrame.textFlow.blockProgression == "rl")
			{
				validator = new CompositionCompleteEventValidator(TestFrame.textFlow,
				new CompositionCompleteEvent(CompositionCompleteEvent.COMPOSITION_COMPLETE, false, false, TestFrame.textFlow, 0, 744));
			}
			else
			{
				validator = new CompositionCompleteEventValidator(TestFrame.textFlow,
				new CompositionCompleteEvent(CompositionCompleteEvent.COMPOSITION_COMPLETE, false, false, TestFrame.textFlow, 0, 831));

			}

			TestFrame.textFlow.fontSize = 30;
    		TestFrame.textFlow.flowComposer.updateAllControllers();
    		assertTrue("Expected CompositionCompleEvent showing after font size changing", validator.validate(1));
		}

		public function UpdateCompleteEventTest():void
		{
			var validator:UpdateCompleteEventValidator = new UpdateCompleteEventValidator(TestFrame.textFlow,
				new UpdateCompleteEvent(UpdateCompleteEvent.UPDATE_COMPLETE, false, false, TestFrame.textFlow, TestFrame));
			var selectionBegin:int = 40;
			var selectionEnd:int = 50;
    		SelManager.selectRange(selectionBegin, selectionEnd);
    		SelManager.deleteNextWord();
    		SelManager.textFlow.flowComposer.updateAllControllers();	// should not result in a compose and not generate an UpdateCompleteEvent
    		assertTrue("Expected One UpdateCompleteEvent showing after deleteNextWord", validator.validate(1));
		}

		// Test cases that should be covered
		// 1. link on part of the line
		// 2. link across several lines
		// For now, only covering first line in link
		public function FlowElementMouseEventTest():void
		{
			var validator:FlowElementMouseEventValidator;

			var cc:ContainerController = SelManager.textFlow.flowComposer.getControllerAt(0);
			if (TestData.id == "FlowElementMouseEventTestScrollingOn")
			{
				cc.verticalScrollPolicy = ScrollPolicy.ON;
				cc.horizontalScrollPolicy = ScrollPolicy.ON;
			}else if (TestData.id == "FlowElementMouseEventTestScrolled")
			{
				cc.verticalScrollPolicy = ScrollPolicy.ON;
				cc.horizontalScrollPolicy = ScrollPolicy.ON;
				var originalXScroll:Number = cc.horizontalScrollPosition;
				var originalYScroll:Number = cc.verticalScrollPosition;
				
				// Copy and paste the entire text, which should cause a scroll event
				SelManager.selectRange(0, int.MAX_VALUE);
				var scrap:TextScrap = TextScrap.createTextScrap(new TextRange(SelManager.textFlow, 0, SelManager.textFlow.textLength));
				var validator1:EventValidator = new EventValidator(SelManager.textFlow, new ScrollEvent(TextLayoutEvent.SCROLL, false, false));
				SelManager.selectRange(int.MAX_VALUE, int.MAX_VALUE);
				SelManager.pasteTextScrap(scrap);
				assertTrue("Expected to get a scroll event, but didn't", validator1.validate(1));
				
				// Verify that the direction and delta in the event are correct
				var scrollEvent:ScrollEvent = validator1.lastEvent as ScrollEvent;
				validateScrollEvent(validator1.lastEvent as ScrollEvent, originalXScroll, originalYScroll);
				
				// scroll to a new position, and check that works as expected
				originalXScroll = cc.horizontalScrollPosition;
				originalYScroll = cc.verticalScrollPosition;
				validator1.reset(new ScrollEvent(TextLayoutEvent.SCROLL, false, false));
				validateScrollEvent(validator1.lastEvent as ScrollEvent, originalXScroll, originalYScroll);
				TestFrame.textFlow.flowComposer.updateAllControllers();
			}
			
			SelManager.selectRange(76, 85);
			SelManager.applyLink("http://www.adobe.com/go/flashplayer","_self" ,false);
			TestFrame.textFlow.flowComposer.updateAllControllers();
			
			var container:DisplayObjectContainer = SelManager.textFlow.flowComposer.getControllerAt(0).container;
			if (TestData.id == "FlowElementMouseEventTestMeasure")
			{	
				container.height = NaN;
				container.width = NaN;	
			}
     		// Get the bounds of the link in TextLine coordinates
    		var boundsInfo:Object = GeometryUtil.getHighlightBounds(SelManager.getSelectionState())[0];
    		var bounds:Rectangle = boundsInfo.rect as Rectangle;
    		var textLine:TextLine = boundsInfo.textLine;

			// get the event mirror off the link
     		var leaf:FlowLeafElement = SelManager.textFlow.findLeaf(SelManager.absoluteStart);
    		var link:LinkElement = leaf.parent as LinkElement;
   			var textFlow:TextFlow = SelManager.textFlow;		// save it for later
     		SelManager.textFlow.interactionManager = null;		// turn off editing

			// before we've done anything, link in normal state
			assertTrue("before we've done anything, link should be in normal state", link.linkState == LinkState.LINK);

    		// listen for rollOver event on the link, send an ersatz mouse_over, which will cause a rollOver
    		// after mouseOver, link should be in hover state
			validator = new FlowElementMouseEventValidator(link, new FlowElementMouseEvent(FlowElementMouseEvent.ROLL_OVER, false, true, link, null));
    		var mouseOverEvent:MouseEvent = new MouseEvent(MouseEvent.MOUSE_OVER, true, false,
    			(bounds.left + bounds.right) / 2, (bounds.top + bounds.bottom) / 2, textLine);
			textLine.dispatchEvent(mouseOverEvent);
    		validator.validate(1);
			assertTrue("after mouseOver, link should be in hover state", link.linkState == LinkState.HOVER);

			// mouseMove
			validator = new FlowElementMouseEventValidator(link, new FlowElementMouseEvent(FlowElementMouseEvent.MOUSE_MOVE, false, true, link, null));
    		var mouseMoveEvent:MouseEvent = new MouseEvent(MouseEvent.MOUSE_MOVE, true, false,
    			(bounds.left + bounds.right) / 2, (bounds.top + bounds.bottom) / 2, textLine);
			textLine.dispatchEvent(mouseMoveEvent);
    		validator.validate(1);

			// mouseDown
			validator = new FlowElementMouseEventValidator(link, new FlowElementMouseEvent(FlowElementMouseEvent.MOUSE_DOWN, false, true, link, null));
    		var mouseDownEvent:MouseEvent = new MouseEvent(MouseEvent.MOUSE_DOWN, true, false,
    			(bounds.left + bounds.right) / 2, (bounds.top + bounds.bottom) / 2, textLine);
			textLine.dispatchEvent(mouseDownEvent);
    		validator.validate(1);
			assertTrue("after mouseDown, link should be in active state", link.linkState == LinkState.ACTIVE);

			// mouseUp -- also generates click
			validator = new FlowElementMouseEventValidator(link, new FlowElementMouseEvent(FlowElementMouseEvent.MOUSE_UP, false, true, link, null));
			var clickValidator:FlowElementMouseEventValidator = new FlowElementMouseEventValidator(link, new FlowElementMouseEvent(FlowElementMouseEvent.CLICK, false, true, link, null));
    		var mouseUpEvent:MouseEvent = new MouseEvent(MouseEvent.MOUSE_UP, true, false,
    			(bounds.left + bounds.right) / 2, (bounds.top + bounds.bottom) / 2, textLine);
			textLine.dispatchEvent(mouseUpEvent);
    		validator.validate(1);
    		clickValidator.validate(1);
			assertTrue("after mouseUp, link should be in hover state", link.linkState == LinkState.HOVER);

			// mouseOut
 			validator = new FlowElementMouseEventValidator(link, new FlowElementMouseEvent(FlowElementMouseEvent.ROLL_OUT, false, true, link, null));
    		var mouseOutEvent:MouseEvent = new MouseEvent(MouseEvent.MOUSE_OUT, true, false,
    			bounds.right + 1, bounds.bottom + 1, textLine);
			textLine.dispatchEvent(mouseOutEvent);
    		validator.validate(1);
 			assertTrue("after mouseOut, link should be in default (normal) state", link.linkState == LinkState.LINK);

    		// avoid tearDown assert about no Selectionmanager
    		textFlow.interactionManager = SelManager;
    		SelManager.selectRange(0, 0);
		}

		
		private function validateScrollEvent(scrollEvent:ScrollEvent, originalXScroll:Number, originalYScroll:Number):void
		{
			var flowComposer:IFlowComposer = SelManager.textFlow.flowComposer;
			var controller:ContainerController = flowComposer.getControllerAt(flowComposer.numControllers - 1);
			if (originalXScroll != controller.horizontalScrollPosition)
			{
				assertTrue("Scrolled horizontally, but got vertical scroll event", scrollEvent.direction == ScrollEventDirection.HORIZONTAL);
				assertTrue("Scroll delta doesn't match expected", scrollEvent.delta == controller.horizontalScrollPosition - originalXScroll);
			}
			if (originalYScroll != controller.verticalScrollPosition)
			{
				assertTrue("Scrolled vertically, but got horizontal scroll event", scrollEvent.direction == ScrollEventDirection.VERTICAL);
				assertTrue("Scroll delta doesn't match expected", scrollEvent.delta == controller.verticalScrollPosition - originalYScroll);
			}
		}
		
		public function scrollEventTest():void
		{
			var textFlow:TextFlow = SelManager.textFlow;
			var controller:ContainerController = textFlow.flowComposer.getControllerAt(0);
			controller.verticalScrollPolicy = ScrollPolicy.ON;
			controller.horizontalScrollPolicy = ScrollPolicy.ON;
			var originalXScroll:Number = controller.horizontalScrollPosition;
			var originalYScroll:Number = controller.verticalScrollPosition;

			// Copy and paste the entire text, which should cause a scroll event
			SelManager.selectRange(0, int.MAX_VALUE);
			var scrap:TextScrap = TextScrap.createTextScrap(new TextRange(textFlow, 0, textFlow.textLength));
			var validator:EventValidator = new EventValidator(SelManager.textFlow, new ScrollEvent(TextLayoutEvent.SCROLL, false, false));
			SelManager.selectRange(int.MAX_VALUE, int.MAX_VALUE);
			SelManager.pasteTextScrap(scrap);
			assertTrue("Expected to get a scroll event, but didn't", validator.validate(1));

			// Verify that the direction and delta in the event are correct
			var scrollEvent:ScrollEvent = validator.lastEvent as ScrollEvent;
			validateScrollEvent(validator.lastEvent as ScrollEvent, originalXScroll, originalYScroll);

			// Now scroll up, and check that works as expected
			originalXScroll = controller.horizontalScrollPosition;
			originalYScroll = controller.verticalScrollPosition;
			var verticalText:Boolean = textFlow.computedFormat.blockProgression == BlockProgression.RL;
			validator.reset(new ScrollEvent(TextLayoutEvent.SCROLL, false, false));
			if (verticalText)
				controller.horizontalScrollPosition = 0;
			else
				controller.verticalScrollPosition = 0;
			validateScrollEvent(validator.lastEvent as ScrollEvent, originalXScroll, originalYScroll);
		}

	}
}



