#!/bin/sh
exec scala "$0" "$@"
!#

import scala.collection.mutable.HashMap
import scala.collection.mutable.Set
import scala.collection.mutable.HashSet
import scala.io.Source

import java.io.{InputStreamReader, BufferedReader}

// 1. Execute ec2-describe-instances
// 2. Parse instance ids for reservation id 
// 3. Execute ec2-terminate-instances with instance ids from step 2 

object TerminateReservation {

	def main(args: Array[String]) {

				
		// check that reservation id is passed in
		if (args.length != 1) {
			println("Usage: sh ec2-terminate-reservation.sh <reservation_id>")
			System.exit(1);
		}

		// describe instances 
		var descInstOutput: List[String] = Nil
		execute("ec2-describe-instances"){ (ln : String)  => descInstOutput = ln :: descInstOutput }

		// parse instance ids
		var matched = false
		var instanceIds: List[String] = Nil 
		for (listLine <- descInstOutput.reverse) {
			
			if (listLine.startsWith("RESERVATION")) {
				var resLineArr = listLine.split("\\t")
				if (resLineArr(1) == args(0)) {
					matched = true
				}
				else
					matched = false
			} else 	if (listLine.startsWith("INSTANCE") && matched) {
				var instLineArr = listLine.split("\\t")
				instanceIds = instLineArr(1) :: instanceIds
			}
		}
		println("Instance ids: " + instanceIds)
		println("Instance ids.length : " + instanceIds.length)

		// terminate instances
		if (instanceIds.length > 0) {
			var termInstOutput: List[String] = Nil
			val instancesStr = instanceIds.reduceLeft[String] { (finalStr, n) =>
				finalStr + " " + n
			}
			execute("ec2-terminate-instances " + instancesStr){ (ln : String)  => termInstOutput = ln :: termInstOutput }
			termInstOutput.foreach ( println )
		}

	}


	def execute(command: String) (output: String=>Unit) : Unit = {
		val commands = command.split(" ")
		//commands.foreach { println }

		val proc = new ProcessBuilder(commands: _*).redirectErrorStream(true).start()
		val ins = new BufferedReader(new InputStreamReader(proc.getInputStream))
		val sb = new StringBuilder

		// handle output from command in a separate thread
		val osReaderThread = new Thread(new Runnable() {
			def run() {
				var ln : String = null
				while({ln = ins.readLine; ln != null}) 
					output(ln)
			}
		})
		osReaderThread.start()

		// suspend main thread until osReaderThread is done
		proc.waitFor

		// wait until output is read
		osReaderThread.join()

		// cleanup
		ins.close()
	}

}

TerminateReservation.main(args)

