<?xml version="1.0" encoding="utf-8"?>
<!--
  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.
-->

<!--Flow from one frame to another  -->

<s:Application
        xmlns="http://ns.adobe.com/mxml/2009"
        xmlns:s="library://ns.adobe.com/flex/spark"
        xmlns:local="UnitTest.*"
        explicitMinWidth="100"
        explicitMinHeight="100"
        width="1100"
        height="800"
        applicationComplete="handleCreationComplete()"
        fontFamily="Verdana">

    <Script>
		<![CDATA[
        import UnitTest.ExtendedClasses.TestSuiteExtended;
        import UnitTest.ExtendedClasses.VellumTestCase;
        import UnitTest.Fixtures.FileRepository;
        import UnitTest.Fixtures.TestApp;
        import UnitTest.Fixtures.TestConfig;

        import flashx.textLayout.elements.TextFlow;
        import flashx.textLayout.tlf_internal;

        import mx.managers.SystemManager;
        import mx.managers.systemClasses.MarshallingSupport;
        import mx.utils.LoaderUtil;

        include "UnitTest/General_Functions.as";

        use namespace tlf_internal;

        // import AND instantiate MarshallingSupport.  Enables being loaded as a sub-swf and loading a sub-swf with marshall plan features
        MarshallingSupport;

        private var curDialog:Object;
        private var useTestSelectDialog:Boolean = false;

        public var testMachineName:String = "unspecified";
        public var testOwner:String = "tcalias";
        public var buildType:String = "Private";
        public var snapshotsOn:String = "false";
        public var normalizedURL:String = "";	// for reading control files
        public var generateReport:String = "false";
        public var antSkipTestFile:String = "";
        public var testStartIndex:Number = 0;
        public var testEndIndex:Number = 0;
        public var rangeOfTests:Boolean = false;
        public var testRunDate:String = "";

        public var testPropertiesPath:String = "";

        private var doSnapshotData:Object;
        private var curTest:VellumTestCase;
        private var beforeTestCallback:Function;
        private var afterTestCallback:Function;
        private var checkMemoryIntervalID:uint = setInterval(checkMemoryUsage, 1000);
        private var snapshotStack:Array;

        private var curURL:String;

        private var curSnapshotTypeToStore:String;
        private var tryToStoreCount:Number = 0;
        private var maxTryToStoreCount:Number = 5;

        //Set this option to have the test run do the visual compare before and after a test.
        [Bindable]
        public var doBeforeAfterCompare:Boolean = false;

        [Bindable]
        public var currentlyUsedMemory:uint = 0;

        public var debugOrRelease:String;
        public var vellumDebugOrRelease:String;

        public var testXMLStore:Object = null;
        public var skipList:Array;

        // The data from these files is read on creationcomplete and
        // placed into the store.  The raw XML can be accessed using
        // the filename as a property name
        // Examples:
        // 	XFLStore.simple
        // 	XFLStore.tableExample
        public var xmlFileNameList:Array = [
            "simple.xml",
            "tableExample.xml",
            "asknot.xml",
            "empty.xml",
            "sampleArabic.xml",
            "aliceExcerpt.xml",
            "HtmlTest.xml"
        ];

        public var reportXMLResults:Boolean = false;

        // this testApp object needs to be used to set
        // the static testApp member of VellumTestCase
        // before any VellumTestCase constructors are called.
        public var testApp:TestApp = new TestApp();

        private var xmlFileNameListLength:int;
        private var xmlFileNameListCounter:int;

        public function checkMemoryUsage():void
        {
            currentlyUsedMemory = Math.round(System.totalMemory / 1000000);
        }

        private function loadAndRunTests():void
        {
            var config:TestConfig = TestConfig.getInstance();
            config.baseURL = normalizedURL;
            config.testXMLStore = XML(testXMLStore);
            // Set up all of the application dependencies that the tests
            // use and store them in a static member of VellumTestCase
            testApp.getTextFlow = function ():TextFlow
            {
                return SystemManager(loadedSWF.content).application["activeFlow"];
            };
            testApp.getDisplayObject = function ():DisplayObject
            {
                return SystemManager(loadedSWF.content).application["rootPanel"];
            };
            testApp.setInteractionManager = SystemManager(loadedSWF.content).application["setInteractionManager"];
            testApp.contentChange = SystemManager(loadedSWF.content).application["changeContent"];
            testApp.detachActiveFlow = SystemManager(loadedSWF.content).application["detachActiveFlow"];
            testApp.changeContainerSetup = SystemManager(loadedSWF.content).application["changeContainerSetup"];

            VellumTestCase.testApp = testApp;

            SystemManager(loadedSWF.content).application["visiblePanels"] = [];
            SystemManager(loadedSWF.content).application["rulerVisible"] = false;

            testRunDate = MakeMySQLDate(new Date());

            testRunner.startTest();
        }

        private var xmlRoot:XML = null;

        public function beforeRunTest(testCase:VellumTestCase, callBack:Function):void
        {
            beforeTestCallback = callBack;
            testCase.doBeforeAfterCompare = doBeforeAfterCompare;
            beforeTestCallback(testCase);
        }

        private function ioErrorPutBaseline(evtObj:IOErrorEvent):void
        {
            // Remove the event listeners to plug up memory leaks.
            if (evtObj)
            {
                evtObj.target.removeEventListener("complete", doSnapShotStoreStack);
                evtObj.target.removeEventListener(IOErrorEvent.IO_ERROR, ioErrorPutBaseline);
                evtObj.target.removeEventListener(HTTPStatusEvent.HTTP_STATUS, httpStatus);
            }
            trace("Error trying to put the baseline.");
            // Continue doing the snapshots.
            doSnapShotStoreStack(null);
        }

        private function doSnapShotStoreStack(evtObj:Event):void
        {
            if (evtObj)
            {
                evtObj.target.removeEventListener("complete", doSnapShotStoreStack);
                evtObj.target.removeEventListener(IOErrorEvent.IO_ERROR, ioErrorPutBaseline);
                evtObj.target.removeEventListener(HTTPStatusEvent.HTTP_STATUS, httpStatus);
            }
            var snapshotType:String = snapshotStack.shift();
            if (snapshotType != null)
            {
                //store result after test

            }
            else
                afterTestCallback(curTest);
        }

        //*********************************************************************/

        /**
         * Read through a test suite and return a new suite of tests
         * that have the minimal flag set and are not in the skip list.
         */
        public function createMinimalSuite(fullSuite:TestSuiteExtended):TestSuiteExtended
        {
            // the way we iterate through tests here and in readTestCaseFiles
            // assumes we have only one level of nesting of test suites,
            // which may not always be true.
            var minimalSuite:TestSuiteExtended = new TestSuiteExtended(this);

            var suiteList:Array = fullSuite.getTests();
            for (var i1:int = 0; i1 < suiteList.length; i1++)
            {
                if (suiteList[i1].minimal)
                {
                    if (skipList)
                    {
                        if (skipList.indexOf(suiteList[i1].testID) == -1)
                        {
                            minimalSuite.addTestDescriptor(suiteList[i1]);
                        }
                    }
                    else
                    {
                        minimalSuite.addTestDescriptor(suiteList[i1]);
                    }
                }
            }
            return minimalSuite;
        }

        /**
         * The machine name is stored in a file named testMachine.txt
         * This is updated from the init task in the ant build.  Once
         * we've retrieved the machine name we generate a file read
         * error to determine where VellumUnit is being run from
         */
        public function readMachineName(event:Event):void
        {
            var fileContents:String = FileRepository.getFile(normalizedURL, "../../test/testMachine.txt");
            if (fileContents)
            {
                var namePattern:RegExp = /testMachineName=(.*)/;
                if (fileContents.match(namePattern))
                {
                    var nameLine:String = fileContents.match(namePattern)[0];
                    testMachineName = nameLine.replace(namePattern, "$1");
                }
                var typePattern:RegExp = /buildType=(.*)/;
                if (fileContents.match(typePattern))
                {
                    var typeLine:String = fileContents.match(typePattern)[0];
                    buildType = typeLine.replace(typePattern, "$1");
                }
                var ownerPattern:RegExp = /testOwner=(.*)/;
                if (fileContents.match(ownerPattern))
                {
                    var ownerLine:String = fileContents.match(ownerPattern)[0];
                    testOwner = ownerLine.replace(ownerPattern, "$1");
                }
                var snapPattern:RegExp = /snapshots=(.*)/;
                if (fileContents.match(snapPattern))
                {
                    var snapLine:String = fileContents.match(snapPattern)[0];
                    snapshotsOn = snapLine.replace(snapPattern, "$1");
                }
                var genPattern:RegExp = /generateReport=(.*)/;
                if (fileContents.match(genPattern))
                {
                    var genLine:String = fileContents.match(genPattern)[0];
                    generateReport = genLine.replace(genPattern, "$1");
                }
                var skipFilePattern:RegExp = /antSkipTestFile=(.*)/;
                if (fileContents.match(skipFilePattern))
                {
                    var skipLine:String = fileContents.match(skipFilePattern)[0];
                    antSkipTestFile = skipLine.replace(skipFilePattern, "$1");
                }
                var startPattern:RegExp = /startTest=(.*)/;
                if (fileContents.match(startPattern))
                {
                    var startLine:String = fileContents.match(startPattern)[0];
                    testStartIndex = Number(startLine.replace(startPattern, "$1"));
                }
                var endPattern:RegExp = /endTest=(.*)/;
                if (fileContents.match(endPattern))
                {
                    var endLine:String = fileContents.match(endPattern)[0];
                    testEndIndex = Number(endLine.replace(endPattern, "$1"));
                }
                rangeOfTests = (testStartIndex != 0) && (testEndIndex != 0);
                /* var filePrefixPattern:RegExp = /testOwner=(.*)/;
                 if (fileContents.match(filePrefixPattern))
                 {
                 var filePrefixLine:String = fileContents.match(filePrefixPattern)[0];
                 filePrefix = filePrefixLine.replace (filePrefixPattern, "$1");
                 }	*/
            }
        }

        public function turnOffSnapshots(event:Event = null):void
        {
            snapshotsOn = "false";
            //  chooseTestRunner();
        }

        public function securityHandler(evtObj:SecurityErrorEvent):void
        {
            trace("ERROR", evtObj.toString());
        }

        /**
         * If we've read in a test index range from testMachine.txt, then go
         * right to running that range of tests
         */
        private function startRangeTests():void
        {
            useTestSelectDialog = true;	// we select the range in the XML for this dialog
            loadAndRunTests();
        }

        private function onLoad_Coverage(ev:Event):void
        {
            loadedSWF.load("CoverageManagerExit.swf");
        }

        //*********************************************************

        public function handleCreationComplete():void
        {
            normalizedURL = LoaderUtil.normalizeURL(loaderInfo);
            TestConfig.getInstance().normalizedUrl = normalizedURL;
            // if we're in the AIR runtime, we get app:/VellumUnit.swf instead of
            // a file:/// URL. This checks for that and changes it to file:///
            if (normalizedURL.charAt(0) == "a")
            {
                var c:Class = Class(ApplicationDomain.currentDomain.getDefinition("flash.filesystem.File"));
                normalizedURL = new c(new c(normalizedURL)["nativePath"])["url"];
            }

            //Security.loadPolicyFile("http://flashqa.macromedia.com/crossdomain.xml");
            xmlFileNameListLength = xmlFileNameList.length;
            for (var i:int = 0; i < xmlFileNameListLength; i++)
            {
                FileRepository.readFile(normalizedURL, "../../test/testFiles/markup/tlf/" + xmlFileNameList[i],
                        onXmlFileListLoadComplete, onXmlFileListError, onXmlFileListSecurityError);
            }
        }

        private function onXmlFileListLoadComplete(event:Event):void
        {
            xmlFileNameListCounter++;
            if (xmlFileNameListCounter == xmlFileNameListLength)
            {
                loadAndRunTests();
                xmlFileNameListCounter = 0;
            }
        }

        private function onXmlFileListError(event:IOErrorEvent):void
        {
            //TODO: Error handlig for xml config files
        }

        private function onXmlFileListSecurityError(event:SecurityErrorEvent):void
        {
            //TODO: Error handlig for xml config files
        }
        ]]>
    </Script>

    <s:VGroup height="100%" width="100%">
        <s:HGroup>
            <!-- <mx:Button label="Run Selected Tests" id="cmdRunSelectedTests" click="onRunTest()" enabled="{canRun}"/> -->
            <s:Label text="memory usage:"/>
            <s:TextInput text="{currentlyUsedMemory}" width="71" height="20"/>
        </s:HGroup>
        <local:TestDescriptorRunner id="testRunner" height="30%" width="100%"/>
        <s:SWFLoader id="loadedSWF" source="Flow.swf" height="536" width="1100"/>
    </s:VGroup>

</s:Application>
