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 forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (forall a. a -> IO (IORef a)
newIORef MailboxInfo
emptyMboxInfo) forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> (forall a. a -> IO (IORef a)
newIORef Int
0)

getMailboxInfo :: IMAPConnection -> IO MailboxInfo
getMailboxInfo :: IMAPConnection -> IO MailboxInfo
getMailboxInfo IMAPConnection
c = forall a. IORef a -> IO a
readIORef 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 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 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 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 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 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 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 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 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 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 :: forall a. 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 <- forall a. IORef a -> IO a
readIORef IORef Int
ref
  a
result <- Int -> IO a
act Int
num
  forall a. IORef a -> (a -> a) -> IO ()
modifyIORef IORef Int
ref (forall a. Num a => a -> a -> a
+Int
1)
  forall (m :: * -> *) a. Monad m => a -> m a
return (a
result, Int
num)

setMailboxInfo :: IMAPConnection -> MailboxInfo -> IO ()
setMailboxInfo :: IMAPConnection -> MailboxInfo -> IO ()
setMailboxInfo IMAPConnection
c = 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 = forall a. IORef a -> (a -> a) -> IO ()
modifyIORef (IMAPConnection -> IORef MailboxInfo
mboxInfo IMAPConnection
c) MailboxInfo -> MailboxInfo
f