/* sbt -- Simple Build Tool
 * Copyright 2009, 2010  Mark Harrah
 */
 package xsbt.boot

import java.io.File


// The entry point to the launcher
object Boot
{
	def main(args: Array[String])
	{
	  val config = parseArgs(args)
	  // If we havne't exited, we set up some hooks and launch
	  System.clearProperty("scala.home") // avoid errors from mixing Scala versions in the same JVM
      System.setProperty("jline.shutdownhook", "false") // shutdown hooks cause class loader leaks
	  System.setProperty("jline.esc.timeout", "0") // starts up a thread otherwise
	  CheckProxy()
	  run(config)
	}
	def parseArgs(args: Array[String]): LauncherArguments = {
	  @annotation.tailrec
	  def parse(args: List[String], isLocate: Boolean, remaining: List[String]): LauncherArguments = 
	    args match {
  	      case "--version" :: rest =>
  	        println("sbt launcher version " + Package.getPackage("xsbt.boot").getImplementationVersion)
  	        exit(1)
  	      case "--locate" :: rest => parse(rest, true, remaining)
  	      case next :: rest => parse(rest, isLocate, next :: remaining)
	      case Nil => new LauncherArguments(remaining.reverse, isLocate)
	    }
	  parse(args.toList, false, Nil)
	}
	
	// this arrangement is because Scala does not always properly optimize away
	// the tail recursion in a catch statement
	final def run(args: LauncherArguments): Unit = runImpl(args) match {
		case Some(newArgs) => run(newArgs)
		case None => ()
	}
	private def runImpl(args: LauncherArguments): Option[LauncherArguments] =
		try
			Launch(args) map exit
		catch
		{
			case b: BootException => errorAndExit(b.toString)
			case r: xsbti.RetrieveException => errorAndExit("Error: " + r.getMessage)
			case r: xsbti.FullReload => Some(new LauncherArguments(r.arguments.toList, false))
			case e: Throwable =>
				e.printStackTrace
				errorAndExit(Pre.prefixError(e.toString))
		}

	private def errorAndExit(msg: String): Nothing =
	{
		System.out.println(msg)
		exit(1)
	}
	private def exit(code: Int): Nothing =
		System.exit(code).asInstanceOf[Nothing]
}