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

import Pre._
import java.io.File
import java.net.URI
import scala.collection.immutable.List

object Find { def apply(config: LaunchConfiguration, currentDirectory: File) = (new Find(config))(currentDirectory) }
class Find(config: LaunchConfiguration)
{
	import config.boot.search
	def apply(currentDirectory: File) =
	{
		val current = currentDirectory.getCanonicalFile
		assert(current.isDirectory)

		lazy val fromRoot = path(current, Nil).filter(hasProject).map(_.getCanonicalFile)
		val found: Option[File] =
			search.tpe match
			{
				case Search.RootFirst => fromRoot.headOption
				case Search.Nearest => fromRoot.lastOption
				case Search.Only =>
					if(hasProject(current))
						Some(current)
					else
						fromRoot match
						{
							case Nil => Some(current)
							case head :: Nil => Some(head)
							case xs =>
								System.err.println("Search method is 'only' and multiple ancestor directories match:\n\t" + fromRoot.mkString("\n\t"))
								System.exit(1)
								None
						}
				case _ => Some(current)
			}
		val baseDirectory = orElse(found, current)
		System.setProperty("user.dir", baseDirectory.getAbsolutePath)
		(ResolvePaths(config, baseDirectory), baseDirectory)
	}
	private def hasProject(f: File) = f.isDirectory && search.paths.forall(p => ResolvePaths(f, p).exists)
	private def path(f: File, acc: List[File]): List[File] = if(f eq null) acc else path(f.getParentFile, f :: acc)
}
object ResolvePaths
{
	def apply(config: LaunchConfiguration, baseDirectory: File): LaunchConfiguration =
		config.map(f => apply(baseDirectory, f))
	def apply(baseDirectory: File, f: File): File =
		if (f.isAbsolute) f
		else
		{
			assert(baseDirectory.isDirectory) // if base directory is not a directory, URI.resolve will not work properly
			val uri = new URI(null, null, f.getPath, null)
			new File(baseDirectory.toURI.resolve(uri))
		}
}