/* sbt -- Simple Build Tool
 * Copyright 2010  Mark Harrah
 */
package sbt
package complete

	import java.io.File

object HistoryCommands
{
	val Start = "!"
	// second characters
	val Contains = "?"
	val Last = "!"
	val ListCommands = ":"

	def ContainsFull = h(Contains)
	def LastFull = h(Last)
	def ListFull = h(ListCommands)

	def ListN = ListFull + "n"
	def ContainsString = ContainsFull + "string"
	def StartsWithString = Start + "string"
	def Previous = Start + "-n"
	def Nth = Start + "n"
	
	private def h(s: String) = Start + s
	def plainCommands = Seq(ListFull, Start, LastFull, ContainsFull)

	def descriptions = Seq(
		LastFull -> "Execute the last command again",
		ListFull -> "Show all previous commands",
		ListN -> "Show the last n commands",
		Nth -> ("Execute the command with index n, as shown by the " + ListFull + " command"),
		Previous -> "Execute the nth command before this one",
		StartsWithString -> "Execute the most recent command starting with 'string'",
		ContainsString -> "Execute the most recent command containing 'string'"
	)
	def helpString = "History commands:\n   " + (descriptions.map{ case (c,d) => c + "    " + d}).mkString("\n   ")
	def printHelp(): Unit =
		println(helpString)
	def printHistory(history: complete.History, historySize: Int, show: Int): Unit =
		 history.list(historySize, show).foreach(println)

		import DefaultParsers._

	val MaxLines = 500
	lazy val num = token(NatBasic, "<integer>")
	lazy val last = Last ^^^ { execute(_ !!) }
	lazy val list = ListCommands ~> (num ?? Int.MaxValue) map { show =>
		(h: History) => { printHistory(h, MaxLines, show); Some(Nil) }
	}
	lazy val execStr = flag('?') ~ token(any.+.string, "<string>") map { case (contains, str) =>
		execute(h => if(contains) h !? str else h ! str)
	}
	lazy val execInt = flag('-') ~ num map { case (neg, value) =>
		execute(h => if(neg) h !- value else h ! value)
	}
	lazy val help = success( (h: History) => { printHelp(); Some(Nil) } )

	def execute(f: History => Option[String]): History => Option[List[String]] = (h: History) =>
	{
		val command = f(h)
		val lines = h.lines.toArray
		command.foreach(lines(lines.length - 1) = _)
		h.path foreach { h => IO.writeLines(h, lines) }
		Some(command.toList)
	}

	val actionParser: Parser[complete.History => Option[List[String]]] =
		Start ~> (help | last | execInt | list | execStr ) // execStr must come last
}