package sbt.complete

import Completion.{ displayStrict, token => ctoken, tokenDisplay }

sealed trait TokenCompletions {
  def hideWhen(f: Int => Boolean): TokenCompletions
}
object TokenCompletions {
  private[sbt] abstract class Delegating extends TokenCompletions { outer =>
    def completions(seen: String, level: Int, delegate: Completions): Completions
    final def hideWhen(hide: Int => Boolean): TokenCompletions = new Delegating {
      def completions(seen: String, level: Int, delegate: Completions): Completions =
        if (hide(level)) Completions.nil else outer.completions(seen, level, delegate)
    }
  }
  private[sbt] abstract class Fixed extends TokenCompletions { outer =>
    def completions(seen: String, level: Int): Completions
    final def hideWhen(hide: Int => Boolean): TokenCompletions = new Fixed {
      def completions(seen: String, level: Int) =
        if (hide(level)) Completions.nil else outer.completions(seen, level)
    }
  }

  val default: TokenCompletions = mapDelegateCompletions((seen, level, c) => ctoken(seen, c.append))

  def displayOnly(msg: String): TokenCompletions = new Fixed {
    def completions(seen: String, level: Int) = Completions.single(displayStrict(msg))
  }
  def overrideDisplay(msg: String): TokenCompletions = mapDelegateCompletions((seen, level, c) => tokenDisplay(display = msg, append = c.append))

  def fixed(f: (String, Int) => Completions): TokenCompletions = new Fixed {
    def completions(seen: String, level: Int) = f(seen, level)
  }
  def mapDelegateCompletions(f: (String, Int, Completion) => Completion): TokenCompletions = new Delegating {
    def completions(seen: String, level: Int, delegate: Completions) = Completions(delegate.get.map(c => f(seen, level, c)))
  }
}