/* 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))
    }
}