{-# 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
/= :: Flag -> Flag -> Bool
$c/= :: Flag -> Flag -> Bool
== :: Flag -> Flag -> Bool
$c== :: 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
showList :: [Flag] -> ShowS
$cshowList :: [Flag] -> ShowS
show :: Flag -> String
$cshow :: Flag -> String
showsPrec :: Int -> Flag -> ShowS
$cshowsPrec :: Int -> 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 (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= [b] -> IO [b]
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 (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= [(b, [Flag])] -> IO [(b, [Flag])]
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 [(b, [Flag], String)]
messages <- a -> IO [(b, [Flag], String)]
forall a b. MailboxReader a b => a -> IO [(b, [Flag], String)]
getAll a
mb
           [(b, [Flag], String)] -> IO [(b, [Flag], String)]
forall (m :: * -> *) a. Monad m => a -> m a
return ([(b, [Flag], String)] -> IO [(b, [Flag], String)])
-> [(b, [Flag], String)] -> IO [(b, [Flag], String)]
forall a b. (a -> b) -> a -> b
$ ((b, [Flag], String) -> Bool)
-> [(b, [Flag], String)] -> [(b, [Flag], String)]
forall a. (a -> Bool) -> [a] -> [a]
filter (\(b
x, [Flag]
_, String
_) -> b
x b -> [b] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [b]
list) [(b, [Flag], String)]
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 ()