module Dustme where
import           Control.Concurrent       (newEmptyMVar, takeMVar)
import           Control.Concurrent.Async (async, cancel, race)
import           Control.DeepSeq          (force)
import           Control.Exception        (bracket, evaluate)
import qualified Data.Text                as T
import qualified Data.Text.IO             as TIO
import           Dustme.Renderer
import           Dustme.Search
import           Dustme.TTY               (withTTY)
import           Dustme.Types
import           System.IO
dustme config = do
  hSetBuffering stdout NoBuffering
  input <- T.lines <$> TIO.getContents
  let applyOp' = applyOp input
  withTTY "/dev/tty0" (setup applyOp' (map mkTrivialMatch input))
mkTrivialMatch = Match 10000 1 0
setup applyOp' initMatch tty = go 0 initMatch (Search "") emptyCache
  where
    getCommand = takeMVar (ttyGetCommand tty)
    go :: Int -> SearchResult -> Search -> SearchCache -> IO ()
    go    index  matches'         search    cache = do
      let matches = case search of
            (Search "") -> initMatch
            _ -> matches'
      
      
      
      r <- race (evaluate $ force matches) getCommand
      s <- case r of
             Left matches' -> renderSearch tty index matches search >> getCommand
             Right x -> return x
      case s of
        Accept  -> TIO.putStrLn (matchText $ matches !! index)
        Up      -> go (clamp (length matches) (index1)) matches search cache
        Down    -> go (clamp (length matches) (index+1)) matches search cache
        Edit op ->
          let (newsearch,newcandidates) = applyOp'  op  search matches
              (searchResult, newcache) =
                getResults newcandidates cache newsearch
          in go 0 searchResult newsearch newcache
clamp hi i
 | i < 0     = 0
 | i >= hi   = hi  1
 | otherwise = i