-- | This module provides bracketed paste support as described at
--
-- http://cirw.in/blog/bracketed-paste
module Graphics.Vty.Input.Paste
  ( parseBracketedPaste
  , bracketedPasteStarted
  , bracketedPasteFinished
  )
where

import qualified Data.ByteString.Char8 as BS8

import Graphics.Vty.Input.Events
import Graphics.Vty.Input.Classify.Types

import Data.List (isPrefixOf, isInfixOf)

bracketedPasteStart :: String
bracketedPasteStart = "\ESC[200~"

bracketedPasteEnd :: String
bracketedPasteEnd = "\ESC[201~"

-- | Does the input start a bracketed paste?
bracketedPasteStarted :: String -> Bool
bracketedPasteStarted = isPrefixOf bracketedPasteStart

-- | Does the input contain a complete bracketed paste?
bracketedPasteFinished :: String -> Bool
bracketedPasteFinished = isInfixOf bracketedPasteEnd

-- | Parse a bracketed paste. This should only be called on a string if
-- both 'bracketedPasteStarted' and 'bracketedPasteFinished' return
-- 'True'.
parseBracketedPaste :: String -> KClass
parseBracketedPaste s =
    let (p, rest) = takeUntil (drop (length bracketedPasteStart) s) bracketedPasteEnd
        rest' = if bracketedPasteEnd `isPrefixOf` rest
                then drop (length bracketedPasteEnd) rest
                else rest
    in Valid (EvPaste $ BS8.pack p) rest'

takeUntil :: (Eq a) => [a] -> [a] -> ([a],[a])
takeUntil [] _ = ([], [])
takeUntil cs sub
  | length cs < length sub      = (cs, [])
  | take (length sub) cs == sub = ([], drop (length sub) cs)
  | otherwise                   = let (pre, suf) = takeUntil (tail cs) sub
                                  in (head cs:pre, suf)