module Network.HaskellNet.IMAP.Connection
    ( IMAPConnection
    , withNextCommandNum
    , setMailboxInfo
    , modifyMailboxInfo
    , newConnection
    , mailbox
    , exists
    , recent
    , flags
    , permanentFlags
    , isWritable
    , isFlagWritable
    , uidNext
    , uidValidity
    , stream
    )
where

import Data.IORef
    ( IORef
    , newIORef
    , readIORef
    , writeIORef
    , modifyIORef
    )
import Control.Applicative

import Network.HaskellNet.BSStream
import Network.HaskellNet.IMAP.Types
    ( MailboxInfo(..)
    , emptyMboxInfo
    , MailboxName
    , Flag
    , UID
    )
import Prelude

data IMAPConnection =
    IMAPC { IMAPConnection -> BSStream
stream :: BSStream
          , IMAPConnection -> IORef MailboxInfo
mboxInfo :: IORef MailboxInfo
          , IMAPConnection -> IORef Int
nextCommandNum :: IORef Int
          }

newConnection :: BSStream -> IO IMAPConnection
newConnection :: BSStream -> IO IMAPConnection
newConnection BSStream
s = BSStream -> IORef MailboxInfo -> IORef Int -> IMAPConnection
IMAPC BSStream
s (IORef MailboxInfo -> IORef Int -> IMAPConnection)
-> IO (IORef MailboxInfo) -> IO (IORef Int -> IMAPConnection)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (MailboxInfo -> IO (IORef MailboxInfo)
forall a. a -> IO (IORef a)
newIORef MailboxInfo
emptyMboxInfo) IO (IORef Int -> IMAPConnection)
-> IO (IORef Int) -> IO IMAPConnection
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> (Int -> IO (IORef Int)
forall a. a -> IO (IORef a)
newIORef Int
0)

getMailboxInfo :: IMAPConnection -> IO MailboxInfo
getMailboxInfo :: IMAPConnection -> IO MailboxInfo
getMailboxInfo IMAPConnection
c = IORef MailboxInfo -> IO MailboxInfo
forall a. IORef a -> IO a
readIORef (IORef MailboxInfo -> IO MailboxInfo)
-> IORef MailboxInfo -> IO MailboxInfo
forall a b. (a -> b) -> a -> b
$ IMAPConnection -> IORef MailboxInfo
mboxInfo IMAPConnection
c

mailbox :: IMAPConnection -> IO MailboxName
mailbox :: IMAPConnection -> IO MailboxName
mailbox IMAPConnection
c = MailboxInfo -> MailboxName
_mailbox (MailboxInfo -> MailboxName) -> IO MailboxInfo -> IO MailboxName
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IMAPConnection -> IO MailboxInfo
getMailboxInfo IMAPConnection
c

exists :: IMAPConnection -> IO Integer
exists :: IMAPConnection -> IO Integer
exists IMAPConnection
c = MailboxInfo -> Integer
_exists (MailboxInfo -> Integer) -> IO MailboxInfo -> IO Integer
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IMAPConnection -> IO MailboxInfo
getMailboxInfo IMAPConnection
c

recent :: IMAPConnection -> IO Integer
recent :: IMAPConnection -> IO Integer
recent IMAPConnection
c = MailboxInfo -> Integer
_recent (MailboxInfo -> Integer) -> IO MailboxInfo -> IO Integer
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IMAPConnection -> IO MailboxInfo
getMailboxInfo IMAPConnection
c

flags :: IMAPConnection -> IO [Flag]
flags :: IMAPConnection -> IO [Flag]
flags IMAPConnection
c = MailboxInfo -> [Flag]
_flags (MailboxInfo -> [Flag]) -> IO MailboxInfo -> IO [Flag]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IMAPConnection -> IO MailboxInfo
getMailboxInfo IMAPConnection
c

permanentFlags :: IMAPConnection -> IO [Flag]
permanentFlags :: IMAPConnection -> IO [Flag]
permanentFlags IMAPConnection
c = MailboxInfo -> [Flag]
_permanentFlags (MailboxInfo -> [Flag]) -> IO MailboxInfo -> IO [Flag]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IMAPConnection -> IO MailboxInfo
getMailboxInfo IMAPConnection
c

isWritable :: IMAPConnection -> IO Bool
isWritable :: IMAPConnection -> IO Bool
isWritable IMAPConnection
c = MailboxInfo -> Bool
_isWritable (MailboxInfo -> Bool) -> IO MailboxInfo -> IO Bool
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IMAPConnection -> IO MailboxInfo
getMailboxInfo IMAPConnection
c

isFlagWritable :: IMAPConnection -> IO Bool
isFlagWritable :: IMAPConnection -> IO Bool
isFlagWritable IMAPConnection
c = MailboxInfo -> Bool
_isFlagWritable (MailboxInfo -> Bool) -> IO MailboxInfo -> IO Bool
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IMAPConnection -> IO MailboxInfo
getMailboxInfo IMAPConnection
c

uidNext :: IMAPConnection -> IO UID
uidNext :: IMAPConnection -> IO UID
uidNext IMAPConnection
c = MailboxInfo -> UID
_uidNext (MailboxInfo -> UID) -> IO MailboxInfo -> IO UID
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IMAPConnection -> IO MailboxInfo
getMailboxInfo IMAPConnection
c

uidValidity :: IMAPConnection -> IO UID
uidValidity :: IMAPConnection -> IO UID
uidValidity IMAPConnection
c = MailboxInfo -> UID
_uidValidity (MailboxInfo -> UID) -> IO MailboxInfo -> IO UID
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IMAPConnection -> IO MailboxInfo
getMailboxInfo IMAPConnection
c

withNextCommandNum :: IMAPConnection -> (Int -> IO a) -> IO (a, Int)
withNextCommandNum :: IMAPConnection -> (Int -> IO a) -> IO (a, Int)
withNextCommandNum IMAPConnection
c Int -> IO a
act = do
  let ref :: IORef Int
ref = IMAPConnection -> IORef Int
nextCommandNum IMAPConnection
c
  Int
num <- IORef Int -> IO Int
forall a. IORef a -> IO a
readIORef IORef Int
ref
  a
result <- Int -> IO a
act Int
num
  IORef Int -> (Int -> Int) -> IO ()
forall a. IORef a -> (a -> a) -> IO ()
modifyIORef IORef Int
ref (Int -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1)
  (a, Int) -> IO (a, Int)
forall (m :: * -> *) a. Monad m => a -> m a
return (a
result, Int
num)

setMailboxInfo :: IMAPConnection -> MailboxInfo -> IO ()
setMailboxInfo :: IMAPConnection -> MailboxInfo -> IO ()
setMailboxInfo IMAPConnection
c = IORef MailboxInfo -> MailboxInfo -> IO ()
forall a. IORef a -> a -> IO ()
writeIORef (IMAPConnection -> IORef MailboxInfo
mboxInfo IMAPConnection
c)

modifyMailboxInfo :: IMAPConnection -> (MailboxInfo -> MailboxInfo) -> IO ()
modifyMailboxInfo :: IMAPConnection -> (MailboxInfo -> MailboxInfo) -> IO ()
modifyMailboxInfo IMAPConnection
c MailboxInfo -> MailboxInfo
f = IORef MailboxInfo -> (MailboxInfo -> MailboxInfo) -> IO ()
forall a. IORef a -> (a -> a) -> IO ()
modifyIORef (IMAPConnection -> IORef MailboxInfo
mboxInfo IMAPConnection
c) MailboxInfo -> MailboxInfo
f