module Text.Parser.Substring
  ( replaceFileOnceWithParser
  , replaceOnceWithParser
  , onceReplacify
  ) where

import           Control.Applicative ((<|>))
import           Data.Attoparsec.Text
import           Data.Monoid ((<>))
import           Data.Text (Text)
import qualified Data.Text.Lazy as Text
import qualified Data.Text.Lazy.Builder as TextBuilder
import           Data.Text.Lazy.Builder (Builder)
import qualified Data.Text.IO as Text

import           Debug.NoTrace (trace)


replaceFileOnceWithParser :: Parser Text -> FilePath -> IO ()
replaceFileOnceWithParser p filePath =
  Text.writeFile filePath =<< replaceOnceWithParser p <$> Text.readFile filePath


replaceOnceWithParser :: Parser Text -> Text -> Text
replaceOnceWithParser p t =
  maybe t (Text.toStrict . TextBuilder.toLazyText)
    $ maybeResult
    $ traceId "fed"
    $ flip feed ""
    $ traceId "parsed"
    $ parse (onceReplacify p) t


onceReplacify :: Parser Text -> Parser Builder
onceReplacify p =
  let firstToMatched =
        (TextBuilder.fromText <$> p)
          <|> ((<>) <$> (TextBuilder.singleton <$> anyChar) <*> firstToMatched)
  in
    (<>) <$> firstToMatched <*> (TextBuilder.fromText <$> takeText)


traceIdVia :: Show b => (a -> b) -> String -> a -> a
traceIdVia via prefix x = trace (prefix ++ ": " ++ show (via x)) x

traceId :: Show a => String -> a -> a
traceId = traceIdVia id