module Network.Mail.Parse.Parsers.Multipart (parseMultipart) where

import qualified Data.ByteString.Char8 as BSC
import qualified Data.ByteString as BS
import Data.Word8
import Data.Attoparsec.ByteString

import Network.Mail.Parse.Utils

isBoundaryMatched :: BSC.ByteString -> Int -> Word8 -> Maybe Int
isBoundaryMatched boundary matchIdx char =
  if char == BS.index boundary matchIdx
    then if matchIdx == boundaryLength - 1
          then Nothing
          else Just $ matchIdx + 1
    else Just 0
  where boundaryLength = BS.length boundary

trimPayload :: BSC.ByteString -> BSC.ByteString -> BSC.ByteString
trimPayload boundary payload = BSC.take trimLength payload
  where payloadLength  = BSC.length payload
        boundaryLength = BSC.length boundary
        trimLength     = payloadLength - boundaryLength + 1

parseMultipart :: BSC.ByteString -> Parser [BSC.ByteString]
parseMultipart boundary =
  do
    _ <- manyTill' anyWord8 (string completeBoundary) <* consumeTillEndLine
    payloads <- many' (scan 0 (isBoundaryMatched completeBoundary) <* consumeTillEndLine)
    return $ map (trimPayload completeBoundary) payloads
  where completeBoundary = BSC.append "--" boundary