/* sbt -- Simple Build Tool
 * Copyright 2008, 2009 Mark Harrah
 */
package sbt

import scala.tools.nsc.{interpreter, util, GenericRunnerCommand, InterpreterLoop, ObjectRunner, Settings}
import util.ClassPath
import java.net.URL

/** This module is an interface to starting the scala interpreter or runner.*/
object object sbt.RunRun
{
	/** Starts an interactive scala interpreter session with the given classpath.*/
	def (Iterable[sbt.Path],sbt.Logger)Option[String]console(Iterable[sbt.Path]classpath: Iterable[sbt.Path]Iterable[Path], sbt.Loggerlog: sbt.LoggerLogger) =
		(sbt.Logger)((scala.tools.nsc.Settings) => Option[String])Option[String]createSettings(sbt.Loggerlog)
		{
			(scala.tools.nsc.Settingssettings: scala.tools.nsc.SettingsSettings) =>
			{
				scala.tools.nsc.Settingssettings.=> scala.tools.nsc.Settings.StringSettingclasspath.(settings.classpath.T)Unitvalue = object sbt.PathPath.(Iterable[sbt.Path])StringmakeString(Iterable[sbt.Path]classpath)
				sbt.Loggerlog.(=> String)Unitinfo(java.lang.String("Starting scala interpreter...")"Starting scala interpreter...")
				sbt.Loggerlog.(=> String)Unitdebug(java.lang.String("  Classpath: ")"  Classpath: " (Any)java.lang.String+ scala.tools.nsc.Settingssettings.=> scala.tools.nsc.Settings.StringSettingclasspath.=> settings.classpath.Tvalue)
				sbt.Loggerlog.(=> String)Unitinfo(java.lang.String("")"")
				object sbt.ControlControl.(=> String,sbt.Logger)(=> Option[String])Option[String]trapUnit(java.lang.String("Error during session: ")"Error during session: ", sbt.Loggerlog)
				{
					val scala.tools.nsc.InterpreterLooploop = ()scala.tools.nsc.InterpreterLoopnew scala.tools.nsc.InterpreterLoopInterpreterLoop
					(=> Unit,sbt.Logger)Option[String]executeTrapExit(scala.tools.nsc.InterpreterLooploop.(scala.tools.nsc.Settings)Unitmain(scala.tools.nsc.Settingssettings), sbt.Loggerlog)
				}
			}
		}
	/** Executes the given function, trapping calls to System.exit. */
	private def (=> Unit,sbt.Logger)Option[String]executeTrapExit(=> Unitf: => Unit, sbt.Loggerlog: sbt.LoggerLogger): Option[String]Option[String] =
	{
		(=> Unit,sbt.Logger)Either[Int,Unit]TrapExit(=> Unitf, sbt.Loggerlog) Option[String]match
		{
			Option[String]case Left(IntexitCode) =>
			{
				Option[String]if(IntexitCode (Int)Boolean== Int(0)0)
				{
					sbt.Loggerlog.(=> String)Unitdebug(java.lang.String("Exited with code 0")"Exited with code 0")
					object NoneNone
				}
				else
					(java.lang.String)Some[java.lang.String]Some(java.lang.String("Nonzero exit code: ")"Nonzero exit code: " (Any)java.lang.String+ IntexitCode)
			}
			None.typecase _ => object NoneNone
		}
	}
	/** Runs the class 'mainClass' using the given classpath and options using the scala runner.*/
	def (String,Iterable[sbt.Path],Seq[String],sbt.Logger)Option[String]run(StringmainClass: StringString, Iterable[sbt.Path]classpath: Iterable[sbt.Path]Iterable[Path], Seq[String]options: Seq[String]Seq[String], sbt.Loggerlog: sbt.LoggerLogger) =
	{
		(sbt.Logger)((scala.tools.nsc.Settings) => Option[String])Option[String]createSettings(sbt.Loggerlog)
		{
			(scala.tools.nsc.Settingssettings: scala.tools.nsc.SettingsSettings) =>
			{
				object sbt.ControlControl.(=> String,sbt.Logger)(=> Option[String])Option[String]trapUnit(java.lang.String("Error during run: ")"Error during run: ", sbt.Loggerlog)
				{
					val List[java.net.URL]classpathURLs = Iterable[sbt.Path]classpath.((sbt.Path) => java.net.URL)Iterable[java.net.URL]map(sbt.Path_.=> java.net.URLasURL).=> List[java.net.URL]toList
					val Array[java.lang.String]bootClasspath = object sbt.FileUtilitiesFileUtilities.(String)Array[java.lang.String]pathSplit(scala.tools.nsc.Settingssettings.=> scala.tools.nsc.Settings.StringSettingbootclasspath.=> settings.bootclasspath.Tvalue)
					val Array[java.net.URL]extraURLs =
						for(((java.lang.String) => java.net.URL)Array[java.net.URL]pathString <- Array[java.lang.String]bootClasspath if java.lang.StringpathString.()Intlength (Int)Boolean> Int(0)0) yield
							(java.io.Filenew java.io.java.io.FileFile(java.lang.StringpathString)).()java.net.URItoURI.()java.net.URLtoURL
					sbt.Loggerlog.(=> String)Unitinfo(java.lang.String("Running ")"Running " (Any)java.lang.String+ StringmainClass (Any)java.lang.String+ java.lang.String(" ...")" ...")
					sbt.Loggerlog.(=> String)Unitdebug(java.lang.String("  Classpath:")"  Classpath:" (Any)java.lang.String+ (List[java.net.URL]classpathURLs (Iterable[java.net.URL])List[java.net.URL]++ Array[java.net.URL]extraURLs).(String,String,String)StringmkString(java.lang.String("\012\011")"\n\t", java.lang.String("\012\011")"\n\t",java.lang.String("")""))
					(=> Unit,sbt.Logger)Option[String]executeTrapExit( object scala.tools.nsc.ObjectRunnerObjectRunner.(List[java.net.URL],String,Seq[String])Unitrun(List[java.net.URL]classpathURLs (Iterable[java.net.URL])List[java.net.URL]++ Array[java.net.URL]extraURLs, StringmainClass, Seq[String]options.=> List[String]toList), sbt.Loggerlog )
				}
			}
		}
	}
	/** If mainClassOption is None, then the interactive scala interpreter is started with the given classpath.
	* Otherwise, the class wrapped by Some is run using the scala runner with the given classpath and
	* options. */
	def (Option[String],Iterable[sbt.Path],Seq[String],sbt.Logger)Option[String]apply(Option[String]mainClassOption: Option[String]Option[String], Iterable[sbt.Path]classpath: Iterable[sbt.Path]Iterable[Path], Seq[String]options: Seq[String]Seq[String], sbt.Loggerlog: sbt.LoggerLogger) =
	{
		Option[String]mainClassOption Option[String]match
		{
			Option[String]case Some(StringmainClass) => (String,Iterable[sbt.Path],Seq[String],sbt.Logger)Option[String]run(StringmainClass, Iterable[sbt.Path]classpath, Seq[String]options, sbt.Loggerlog)
			Option[String]case object NoneNone => (Iterable[sbt.Path],sbt.Logger)Option[String]console(Iterable[sbt.Path]classpath, sbt.Loggerlog)
		}
	}
	/** Create a settings object and execute the provided function if the settings are created ok.*/
	private def (sbt.Logger)((scala.tools.nsc.Settings) => Option[String])Option[String]createSettings(sbt.Loggerlog: sbt.LoggerLogger)((scala.tools.nsc.Settings) => Option[String]f: Settings => Option[String]) =
	{
		val scala.tools.nsc.GenericRunnerCommandcommand = (List[String],(String) => Unit)scala.tools.nsc.GenericRunnerCommandnew scala.tools.nsc.GenericRunnerCommandGenericRunnerCommand(object NilNil, Stringmessage => sbt.Loggerlog.(=> String)Uniterror(Stringmessage))
		Option[String]if(scala.tools.nsc.GenericRunnerCommandcommand.=> Booleanok)
			(scala.tools.nsc.Settings)Option[String]f(scala.tools.nsc.GenericRunnerCommandcommand.=> scala.tools.nsc.GenericRunnerSettingssettings)
		else
			(java.lang.String)Some[java.lang.String]Some(scala.tools.nsc.GenericRunnerCommandcommand.=> java.lang.StringusageMsg)
	}
}