module Network.DomainAuth.Mail.XMail (
    XMail (..),
    initialXMail,
    pushField,
    pushBody,
    finalizeMail,
) where

import qualified Data.ByteString.Char8 as BS
import Data.Sequence (fromList)
import Network.DomainAuth.Mail.Types
import Network.DomainAuth.Utils

----------------------------------------------------------------

-- | Type for temporary data to parse e-mail message.
data XMail = XMail
    { XMail -> Header
xmailHeader :: Header
    , XMail -> [RawBodyChunk]
xmailBody :: [RawBodyChunk]
    }
    deriving (XMail -> XMail -> Bool
(XMail -> XMail -> Bool) -> (XMail -> XMail -> Bool) -> Eq XMail
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: XMail -> XMail -> Bool
== :: XMail -> XMail -> Bool
$c/= :: XMail -> XMail -> Bool
/= :: XMail -> XMail -> Bool
Eq, Int -> XMail -> ShowS
[XMail] -> ShowS
XMail -> String
(Int -> XMail -> ShowS)
-> (XMail -> String) -> ([XMail] -> ShowS) -> Show XMail
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> XMail -> ShowS
showsPrec :: Int -> XMail -> ShowS
$cshow :: XMail -> String
show :: XMail -> String
$cshowList :: [XMail] -> ShowS
showList :: [XMail] -> ShowS
Show)

-- | Initial value for 'XMail'.
initialXMail :: XMail
initialXMail :: XMail
initialXMail = Header -> [RawBodyChunk] -> XMail
XMail [] []

-- | Storing field key and field value to the temporary data.
pushField :: RawFieldKey -> RawFieldValue -> XMail -> XMail
pushField :: RawBodyChunk -> RawBodyChunk -> XMail -> XMail
pushField RawBodyChunk
key RawBodyChunk
val XMail
xmail =
    XMail
xmail
        { xmailHeader = fld : xmailHeader xmail
        }
  where
    fld :: Field
fld = RawBodyChunk -> RawBodyChunk -> [RawBodyChunk] -> Field
Field RawBodyChunk
ckey RawBodyChunk
key (RawBodyChunk -> [RawBodyChunk]
blines RawBodyChunk
val)
    ckey :: RawBodyChunk
ckey = RawBodyChunk -> RawBodyChunk
canonicalizeKey RawBodyChunk
key

-- | Storing body chunk to the temporary data.
pushBody :: RawBodyChunk -> XMail -> XMail
pushBody :: RawBodyChunk -> XMail -> XMail
pushBody RawBodyChunk
bc XMail
xmail =
    XMail
xmail
        { xmailBody = bc : xmailBody xmail
        }

-- | Converting 'XMail' to 'Mail'.
finalizeMail :: XMail -> Mail
finalizeMail :: XMail -> Mail
finalizeMail XMail
xmail =
    Mail
        { mailHeader :: Header
mailHeader = Header -> Header
forall a. [a] -> [a]
reverse (Header -> Header) -> (XMail -> Header) -> XMail -> Header
forall b c a. (b -> c) -> (a -> b) -> a -> c
. XMail -> Header
xmailHeader (XMail -> Header) -> XMail -> Header
forall a b. (a -> b) -> a -> b
$ XMail
xmail
        , mailBody :: Body
mailBody = [RawBodyChunk] -> Body
forall a. [a] -> Seq a
fromList ([RawBodyChunk] -> Body)
-> (XMail -> [RawBodyChunk]) -> XMail -> Body
forall b c a. (b -> c) -> (a -> b) -> a -> c
. RawBodyChunk -> [RawBodyChunk]
blines (RawBodyChunk -> [RawBodyChunk])
-> (XMail -> RawBodyChunk) -> XMail -> [RawBodyChunk]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [RawBodyChunk] -> RawBodyChunk
BS.concat ([RawBodyChunk] -> RawBodyChunk)
-> (XMail -> [RawBodyChunk]) -> XMail -> RawBodyChunk
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [RawBodyChunk] -> [RawBodyChunk]
forall a. [a] -> [a]
reverse ([RawBodyChunk] -> [RawBodyChunk])
-> (XMail -> [RawBodyChunk]) -> XMail -> [RawBodyChunk]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. XMail -> [RawBodyChunk]
xmailBody (XMail -> Body) -> XMail -> Body
forall a b. (a -> b) -> a -> b
$ XMail
xmail
        }