{-# LANGUAGE OverloadedStrings, ViewPatterns #-}
module Text.HTML.TagStream.Stream where

import Data.ByteString (ByteString)
import Data.Attoparsec.Char8 (parseOnly)
import qualified Data.ByteString.Char8 as S
import Data.Conduit
import Text.HTML.TagStream.Parser
import Text.HTML.TagStream.Types

-- | like concatMap, with a accumerator.
--
-- Since 0.0.0
tokenStream :: Resource m => Conduit ByteString m Token
tokenStream = conduitState S.empty push close
  where
    push accum input =
        case parseOnly html (accum `S.append` input) of
            Left err -> fail err
            Right (splitAccum -> (accum', tokens)) -> return (accum', Producing tokens)

    close s = return $ if S.null s then [] else [Text s]

    splitAccum :: [Token] -> (ByteString, [Token])
    splitAccum [] = (S.empty, [])
    splitAccum (reverse -> (Incomplete s : xs)) = (s, reverse xs)
    splitAccum tokens = (S.empty, tokens)