module Codec.MIME.String.Types
      (
       ParseM, PartNumber, Headers,
       Header(Header, h_raw_header, h_raw_name, h_name, h_body),
       Message(..), MessageInfo(..), Multipart(Multipart),
       MessageContent(NoContent, Body, Data, Mixed, Alternative,
                      Parallel, Digest, RFC822),
       mkData, mkBody,
       digest_content_type, ascii_text_content_type,
      )
      where

import Codec.MIME.String.Date (FullDate)
import Codec.MIME.String.Headers
      (
       ContentType(ContentType), ContentDescription, ContentTransferEncoding,
       Parameter(Parameter), From, To, Subject,
      )
import Codec.MIME.String.Internal.Utils (my_lines)

import Control.Monad.State (State)

type Headers = [Header]
data Header = Header {
                  h_raw_header :: [String],
                  h_raw_name :: String,
                  h_name :: String,
                  h_body :: String
              }
    deriving (Show, Read)

data MessageInfo = MessageInfo {
                       mi_headers :: Headers,
                       mi_from :: Maybe From,
                       mi_to :: Maybe To,
                       mi_subject :: Maybe Subject,
                       mi_date :: Maybe FullDate,
                       mi_content_description :: Maybe ContentDescription
                   }
    deriving (Show, Read)
data MessageContent = NoContent ContentType
                    | Body ContentType FilePath String -- UTF-8 text
                    | Data (Maybe ContentTransferEncoding)
                           ContentType FilePath String -- 8-bit data
                    | Mixed       Multipart
                    | Alternative Multipart
                    | Parallel    Multipart
                    | Digest      Multipart
                    | RFC822 String{- unparsed message-} FilePath Message
    deriving (Show, Read)

type ParseM a = State PartNumber a

mkBody :: ContentType -> FilePath -> String -> ParseM MessageContent
mkBody ct fp s = return $ Body ct fp $ unlines $ my_lines s

mkData :: Maybe ContentTransferEncoding -> ContentType -> FilePath
       -> String -> ParseM MessageContent
mkData m_cte ct fp s = return $ Data m_cte ct fp s

data Multipart = Multipart String    -- Preamble
                           [Message] -- The messages themselves
                           String    -- Epilogue
    deriving (Show, Read)

type PartNumber = Integer

data Message = Message {
                   m_part_number :: PartNumber,
                   m_message_info :: MessageInfo,
                   m_message_content :: MessageContent
               }
    deriving (Show, Read)

ascii_text_content_type :: ContentType
ascii_text_content_type
 = ContentType "text" "plain" [Parameter "charset" "US-ASCII"]

digest_content_type :: ContentType
digest_content_type = ContentType "message" "rfc822" []