<?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.

-->
<s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009"
                   xmlns:local="*"
                   xmlns:mx="library://ns.adobe.com/flex/mx"
                   xmlns:s="library://ns.adobe.com/flex/spark" 
                   invoke="checkargs(event)"
                   >
    <fx:Script>
        <![CDATA[
            // in theory, all new tags are added to AntClasses.as
            // and therefore force-linking this should initialize
            // all tag handlers
            import AntClasses; AntClasses;
            import org.apache.flex.ant.Ant;
            import org.apache.flex.ant.tags.Copy;
            import org.apache.flex.ant.tags.Get;
            import org.apache.flex.ant.tags.Checksum;
            
            private function checkargs(event:InvokeEvent):void
            {
				var targets:Array = [];

				var nextIsAntFile:Boolean;
				
                for each (var s:String in event.arguments)
				{
					if (s == "-f")
					{
						nextIsAntFile = true;
					}
					else if (nextIsAntFile)
					{
						nextIsAntFile = false;
						antfilename = s;
					}
					else if (s.indexOf("-f ") != -1)
					{
						antfilename = s.substr(3);
					}
					else if (s.indexOf("-D") != -1)
					{
						s = s.substr(2);
						var c:int = s.indexOf("=");
						if (c != -1)
						{
							var parts:Array = s.split("=");
							context[parts[0]] = parts[1];
						}
						else
							context[s] = true;
					}
					else
						targets.push(s);
				}
				context.targets = targets.join(",");
                test();
            }
            
			private var context:Object = {};
			
			private var antfilename:String = "build.xml";
			
            public function test():void
            {
                ant = new Ant();
                ant.output = output;
                var file:File = File.applicationDirectory;
                file = file.resolvePath(antfilename);
                addEventListener(Event.ENTER_FRAME, enterFrameHandler);
                if (!ant.processXMLFile(file, context, true))
                {
                    ant.addEventListener(Event.COMPLETE, completeHandler);
                    ant.addEventListener(ProgressEvent.PROGRESS, progressEventHandler);
                    // redispatch keyboard events off of ant so input task can see them
                    systemManager.stage.addEventListener(KeyboardEvent.KEY_DOWN, ant_keyDownHandler);
                    pb.source = ant;
                }
                else
                    completeHandler(null);
            }
            
            private function progressEventHandler(event:ProgressEvent):void
            {
                if (ant.progressClass is Copy)
                {
                    pb.label = "Copying %1 of %2";
                }
                else if (ant.progressClass is Get)
                {
                    pb.label = "Downloading bytes %1 of %2";                    
                }
                else if (ant.progressClass is Checksum)
                {
                    pb.label = "Computing checksum: bytes %1 of %2";                    
                }
            }
            
            private function completeHandler(event:Event):void
            {
                var failureMode:Boolean = context.expectfailure;
                var msg:String = Ant.currentAnt.project.failureMessage;
                
                if (failureMode && !Ant.currentAnt.project.status)
                    output(msg ? msg : "no failure message provided");
                
                if (Ant.currentAnt.project.status)
                    output(failureMode ? "FAILURE" : "SUCCESS!");
                else
                    output(failureMode ? "SUCCESS" : "FAILURE!");
                
                var successCode:int = failureMode ? 255 : 0;
                var failureCode:int = failureMode ? 0 : 255;
                
                if (context.exitwhendone)
                    NativeApplication.nativeApplication.exit(Ant.currentAnt.project.status ? successCode : failureCode);
            }
            
            private var ant:Ant;
            
            private function output(s:String):void
            {
                console.text += s + "\n";
                callLater(scrollConsoleToBottom);
            }
            
            private function scrollConsoleToBottom():void
            {
                console.verticalScrollPosition = console.maxVerticalScrollPosition;
            }
            
            private function enterFrameHandler(event:Event):void
            {
                ant.doCallback();
            }
            
            private function ant_keyDownHandler(event:KeyboardEvent):void
            {
                ant.dispatchEvent(event);
            }
        ]]>
    </fx:Script>
    <s:layout>
        <s:VerticalLayout />
    </s:layout>
    <mx:TextArea id="console" width="100%" height="100%" fontFamily="Courier New" />
    <mx:ProgressBar id="pb" width="100%" mode="event" label="" />
</s:WindowedApplication>