    {-# LANGUAGE Safe #-}
    {-
    Copyright (c) 2005-2011 John Goerzen <jgoerzen@complete.org>

    All rights reserved.

    For license and copyright information, see the file LICENSE
    -}

    {- |
       Module     : Network.Email.Mailbox
       Copyright  : Copyright (C) 2005-2011 John Goerzen
       SPDX-License-Identifier: BSD-3-Clause

       Stability  : stable
       Portability: portable

    General support for e-mail mailboxes

    Written by John Goerzen, jgoerzen\@complete.org
    -}

    module Network.Email.Mailbox(Flag(..), Flags, Message,
                                  MailboxReader(..),
                                  MailboxWriter(..))
    where

    {- | The flags which may be assigned to a message. -}
    data Flag =
               SEEN
               | ANSWERED
               | FLAGGED
               | DELETED
               | DRAFT
               | FORWARDED
               | OTHERFLAG String
               deriving (Flag -> Flag -> Bool
    (Flag -> Flag -> Bool) -> (Flag -> Flag -> Bool) -> Eq Flag
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: Flag -> Flag -> Bool
    == :: Flag -> Flag -> Bool
    $c/= :: Flag -> Flag -> Bool
    /= :: Flag -> Flag -> Bool
    Eq, Int -> Flag -> ShowS
    [Flag] -> ShowS
    Flag -> String
    (Int -> Flag -> ShowS)
    -> (Flag -> String) -> ([Flag] -> ShowS) -> Show Flag
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> Flag -> ShowS
    showsPrec :: Int -> Flag -> ShowS
    $cshow :: Flag -> String
    show :: Flag -> String
    $cshowList :: [Flag] -> ShowS
    showList :: [Flag] -> ShowS
    Show)

    {- | Convenience shortcut -}
    type Flags = [Flag]

    {- | A Message is represented as a simple String. -}
    type Message = String

    {- | Main class for readable mailboxes.

    The mailbox object /a/ represents zero or more 'Message's.  Each message
    has a unique identifier /b/ in a format specific to each given mailbox.
    This identifier may or may not be persistent.

    Functions which return a list are encouraged -- but not guaranteed -- to
    do so lazily.

    Implementing classes must provide, at minimum, 'getAll'.
    -}
    class (Show a, Show b, Eq b) => MailboxReader a b where
        {- | Returns a list of all unique identifiers. -}
        listIDs :: a -> IO [b]
        {- | Returns a list of all unique identifiers as well as all flags. -}
        listMessageFlags :: a -> IO [(b, Flags)]
        {- | Returns a list of all messages, including their content,
           flags, and unique identifiers. -}
        getAll :: a -> IO [(b, Flags, Message)]
        {- | Returns information about specific messages. -}
        getMessages :: a -> [b] -> IO [(b, Flags, Message)]

        listIDs a
    mb = a -> IO [(b, [Flag])]
    forall a b. MailboxReader a b => a -> IO [(b, [Flag])]
    listMessageFlags a
    mb IO [(b, [Flag])] -> ([(b, [Flag])] -> IO [b]) -> IO [b]
    forall a b. IO a -> (a -> IO b) -> IO b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= [b] -> IO [b]
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ([b] -> IO [b])
    -> ([(b, [Flag])] -> [b]) -> [(b, [Flag])] -> IO [b]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ((b, [Flag]) -> b) -> [(b, [Flag])] -> [b]
    forall a b. (a -> b) -> [a] -> [b]
    map (b, [Flag]) -> b
    forall a b. (a, b) -> a
    fst
        listMessageFlags a
    mb = a -> IO [(b, [Flag], String)]
    forall a b. MailboxReader a b => a -> IO [(b, [Flag], String)]
    getAll a
    mb IO [(b, [Flag], String)]
    -> ([(b, [Flag], String)] -> IO [(b, [Flag])]) -> IO [(b, [Flag])]
    forall a b. IO a -> (a -> IO b) -> IO b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= [(b, [Flag])] -> IO [(b, [Flag])]
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ([(b, [Flag])] -> IO [(b, [Flag])])
    -> ([(b, [Flag], String)] -> [(b, [Flag])])
    -> [(b, [Flag], String)]
    -> IO [(b, [Flag])]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    .
                               ((b, [Flag], String) -> (b, [Flag]))
    -> [(b, [Flag], String)] -> [(b, [Flag])]
    forall a b. (a -> b) -> [a] -> [b]
    map (\(b
    i, [Flag]
    f, String
    _) -> (b
    i, [Flag]
    f))
        getMessages a
    mb [b]
    list =
            do messages <- a -> IO [(b, [Flag], String)]
    forall a b. MailboxReader a b => a -> IO [(b, [Flag], String)]
    getAll a
    mb
               return $ filter (\(b
    x, [Flag]
    _, String
    _) -> b
    x b -> [b] -> Bool
    forall a. Eq a => a -> [a] -> Bool
    forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
    `elem` [b]
    list) messages

    class (MailboxReader a b) => MailboxWriter a b where
        appendMessages :: a -> [(Flags, Message)] -> IO [b]
        deleteMessages :: a -> [b] -> IO ()
        addFlags :: a -> [b] -> Flags -> IO ()
        removeFlags :: a -> [b] -> Flags -> IO ()
        setFlags :: a -> [b] -> Flags -> IO ()