<?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:s="library://ns.adobe.com/flex/spark" 
					   xmlns:mx="library://ns.adobe.com/flex/mx"
                       invoke="checkArgs(event)">
	<fx:Declarations>
		<!-- Place non-visual elements (e.g., services, value objects) here -->
	</fx:Declarations>
	<fx:Script>
		<![CDATA[
			import mx.utils.Base64Decoder;
			
			private var mailFile:File = new File();
			private var fs:FileStream;
			private var flexDir:String;
			private var gotone:Boolean = false;

            private function checkArgs(event:InvokeEvent):void
            {
                var args:Array = event.arguments;
                if (args.length > 0)
                {
					var wd:File = event.currentDirectory;
					flexDir = wd.nativePath;
					var c:int = flexDir.indexOf(File.separator + "mustella" + File.separator + "utilities");
					if (c != -1)
					{
						flexDir = flexDir.substr(0, c);
					}
                    mailFile.nativePath = dir.text = args[0];
                    callLater(autoStep2, [flexDir]);
                }
				else
					nativeApplication.exit(-1);
            }
            
            private function autoStep2(flexDir:String):void
            {
                fs = new FileStream();
                fs.open(mailFile, FileMode.READ);
                statusLog.text = fs.readUTFBytes(fs.bytesAvailable);
                fs.close();
                callLater(autoStep3);
            }
            
            private function autoStep3():void
            {
                computePatches();
                callLater(autoStep4);    
            }
            
            private function autoStep4():void
            {
                this.nativeApplication.exit(gotone ? 0 : 2);   
            }
			
			private function browse():void
			{
				mailFile.addEventListener(Event.SELECT, selectHandler);
				mailFile.browseForOpen("Mail File");
			}
			
			private function selectHandler(event:Event):void
			{
				dir.text = mailFile.nativePath;	
			}
			
			private var SEARCH_MODE:int = 0;
			private var FROM_SEARCH_MODE:int = 1;
			private var PART_SEARCH_MODE:int = 2;
			private var DELIMITER_SEARCH_MODE:int = 3;
			private var PART_HEADER_MODE:int = 4;
			private var PART_MODE:int = 5;
			private var ATTACHMENT_MODE:int = 6;
			private var PART_TYPE_MODE:int = 7;
			private var BOUNDARY_SEARCH_MODE:int = 8;
			
			private function computePatches():void
			{
				mailFile.nativePath = dir.text;
			
				var replyAddr:String;
				var partDelimiter:String;
				var contentEncoding:String;
				var contentType:String;
				var part:String;
				var c:int;
				var c2:int;
				var mode:int = SEARCH_MODE;
				var lines:Array = statusLog.text.split("\n");
				var modFiles:Array = [];
				var n:int = lines.length;
				for (var i:int = 0; i < n; i++)
				{
					var line:String = lines[i];
					switch (mode)
					{
						case SEARCH_MODE:
						{
							if (line.indexOf("Content-Type") == 0)
							{
								mode = PART_TYPE_MODE;
								i--;
							}
							else if (line.indexOf("From") == 0)
							{
								mode = FROM_SEARCH_MODE;
							}
							break;
						}
						case FROM_SEARCH_MODE:
						{
							if (line.indexOf("From: ") == 0)
							{
								c = line.indexOf("<");
								c2 = line.indexOf(">");
								replyAddr = line.substring(c+1, c2);
								mode = DELIMITER_SEARCH_MODE;
							}
							break;
						}
						case DELIMITER_SEARCH_MODE:
						{
							if (line.indexOf("Content-Type: multipart/alternative") == 0
								|| line.indexOf("Content-Type: multipart/mixed") == 0)
							{
								c = line.indexOf("boundary=");
								if (c == -1)
								{
									mode= BOUNDARY_SEARCH_MODE;
								}
								else
								{
									partDelimiter = line.substr(c + 9);
									if (partDelimiter.charAt(0) == '"')
										partDelimiter = partDelimiter.substr(1, partDelimiter.length - 2);
									mode = PART_SEARCH_MODE;
								}
								break;
							}
							break;	
						}
						case PART_SEARCH_MODE:
						{
							if (line.indexOf("--" + partDelimiter) == 0)
							{
								mode = PART_TYPE_MODE;
							}
							break;
						}
						case PART_TYPE_MODE:
						{
							part = "";
							if (line.indexOf("Content-Type") == 0)
							{
								c = line.indexOf(";");
								contentType = line.substring(14, c);
								if (contentType == "application/octet-stream")
									mode = ATTACHMENT_MODE;
								else
									mode = PART_MODE;
							}
							break;
						}
						case ATTACHMENT_MODE:
						{
							if (line.indexOf("Content-Transfer-Encoding") == 0)
							{
								contentEncoding = line.substring(27);
								mode = PART_MODE;
							}
							break;
						}
						case BOUNDARY_SEARCH_MODE:
						{
							c = line.indexOf("boundary");
							if (c != -1)
							{
								partDelimiter = line.substr(c + 9);
								if (partDelimiter.charAt(0) == '"')
									partDelimiter = partDelimiter.substr(1, partDelimiter.length - 2);
								mode = PART_SEARCH_MODE;
							}
							break;
						}
						case PART_MODE:
						{
							if (line.indexOf("--" + partDelimiter) == 0)
							{
								mode = SEARCH_MODE;
								if (contentType == "application/octet-stream" &&
									contentEncoding == "base64")
								{
									var decoder:Base64Decoder = new Base64Decoder();
									decoder.decode(part);
									var ba:ByteArray = decoder.toByteArray();
									ba.position = 0;
									part = ba.readUTFBytes(ba.bytesAvailable);
								}
								c = part.indexOf("diff --git");
								if (c != -1)
								{
									gotone = true;
									part = part.substring(c);
									var timeString:String = new Date().time.toString();
									var fileName:String = replyAddr + timeString + ".patch";
									fileName = flexDir + File.separator + fileName;
									var file:File = new File(fileName);
									var fs:FileStream = new FileStream();
									fs.open(file, FileMode.WRITE);
									fs.writeUTFBytes(part);
									fs.close();
									fileName = replyAddr + timeString + ".reply";
									fileName = flexDir + File.separator + fileName;
									file = new File(fileName);
									fs = new FileStream();
									fs.open(file, FileMode.WRITE);
									fs.writeUTFBytes(replyAddr);
									fs.close();
								}
							}
							else
								part += line + "\n";
						}							
						break;
					}
					
				}
				
			}
			
		]]>
	</fx:Script>
	<s:layout>
		<s:VerticalLayout />
	</s:layout>
	<s:HGroup width="100%">
		<s:Label text="Mail File:" />
		<s:TextInput id="dir" width="100%" toolTip="The mustella dir, not the tests dir"/>
		<s:Button label="Browse..." click="browse()" />
	</s:HGroup>
	<s:Label text="Copy and paste Git Status below" />
	<s:TextArea id="statusLog" width="100%" change="doneLabel.visible=false"/>
	<s:HGroup>
		<s:Button label="Compute Tests" enabled="{statusLog.text.length > 0}" click="callLater(computePatches)" />
		<s:Label id="doneLabel" visible="false" text="Wrote changes.txt. Use mini_run.sh -changes" />
	</s:HGroup>
	<s:TextArea id="output" width="100%" editable="false" lineBreak="explicit" horizontalScrollPolicy="auto" />
</s:WindowedApplication>
