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

import           Control.Applicative ((<|>))
import           Data.Attoparsec.Text
import           Data.Maybe (fromMaybe)
import           Data.Monoid ((<>), mempty)
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


-- TODO: 失敗した場合に元のテキストを返す
replaceOnceWithParser :: Parser Text -> Text -> Text
replaceOnceWithParser p =
  Text.toStrict
    . TextBuilder.toLazyText
    . fromMaybe mempty
    . maybeResult
    . traceId "fed"
    . flip feed ""
    . traceId "parsed"
    . parse (onceReplacify p)


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