-- | Contains message-related actions, like retrieving your own inbox
--   and sending other users private messages.
module Reddit.Actions.Message
  ( getInbox
  , getInbox'
  , getUnread
  , getUnread'
  , markRead
  , sendMessage
  , sendMessageWithCaptcha
  , replyMessage ) where

import Reddit.Types.Captcha
import Reddit.Types.Empty
import Reddit.Types.Listing
import Reddit.Types.Message
import Reddit.Types.Options
import Reddit.Types.Reddit
import Reddit.Types.Thing
import Reddit.Types.User
import qualified Reddit.Routes.Message as Route
import qualified Reddit.Routes.Thing as Route

import Data.Default.Class
import Data.Text (Text)
import Network.API.Builder.Query

-- | Get the message inbox for the current user.
getInbox :: Monad m => RedditT m (Listing MessageKind Message)
getInbox :: RedditT m (Listing MessageKind Message)
getInbox = Route -> RedditT m (Listing MessageKind Message)
forall a (m :: * -> *).
(FromJSON a, Monad m) =>
Route -> RedditT m a
runRoute (Route -> RedditT m (Listing MessageKind Message))
-> Route -> RedditT m (Listing MessageKind Message)
forall a b. (a -> b) -> a -> b
$ Bool -> Options MessageKind -> Route
Route.inbox Bool
False Options MessageKind
forall a. Default a => a
def

-- | Don't use this for watching for new messages, Reddit's ordering on
-- |   inbox messages is odd and not likely to work how you expect.
getInbox' :: Monad m => Bool -> Options MessageKind -> RedditT m (Listing MessageKind Message)
getInbox' :: Bool
-> Options MessageKind -> RedditT m (Listing MessageKind Message)
getInbox' Bool
m Options MessageKind
o = Route -> RedditT m (Listing MessageKind Message)
forall a (m :: * -> *).
(FromJSON a, Monad m) =>
Route -> RedditT m a
runRoute (Route -> RedditT m (Listing MessageKind Message))
-> Route -> RedditT m (Listing MessageKind Message)
forall a b. (a -> b) -> a -> b
$ Bool -> Options MessageKind -> Route
Route.inbox Bool
m Options MessageKind
o

-- | Get any unread messages for the current user.
getUnread :: Monad m => RedditT m (Listing MessageKind Message)
getUnread :: RedditT m (Listing MessageKind Message)
getUnread = Route -> RedditT m (Listing MessageKind Message)
forall a (m :: * -> *).
(FromJSON a, Monad m) =>
Route -> RedditT m a
runRoute (Route -> RedditT m (Listing MessageKind Message))
-> Route -> RedditT m (Listing MessageKind Message)
forall a b. (a -> b) -> a -> b
$ Bool -> Options MessageKind -> Route
Route.unread Bool
False Options MessageKind
forall a. Default a => a
def

-- | Get unread messages for the current user, with options.
getUnread' :: Monad m
           => Bool -- ^ Whether the orangered notifier should be marked "off"
           -> Options MessageKind
           -> RedditT m (Listing MessageKind Message)
getUnread' :: Bool
-> Options MessageKind -> RedditT m (Listing MessageKind Message)
getUnread' Bool
m Options MessageKind
o = Route -> RedditT m (Listing MessageKind Message)
forall a (m :: * -> *).
(FromJSON a, Monad m) =>
Route -> RedditT m a
runRoute (Route -> RedditT m (Listing MessageKind Message))
-> Route -> RedditT m (Listing MessageKind Message)
forall a b. (a -> b) -> a -> b
$ Bool -> Options MessageKind -> Route
Route.unread Bool
m Options MessageKind
o

-- | Mark a message as read.
markRead :: (ToQuery a, Thing a, Monad m) => a -> RedditT m ()
markRead :: a -> RedditT m ()
markRead = RedditT m Empty -> RedditT m ()
forall (m :: * -> *). Monad m => m Empty -> m ()
nothing (RedditT m Empty -> RedditT m ())
-> (a -> RedditT m Empty) -> a -> RedditT m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Route -> RedditT m Empty
forall a (m :: * -> *).
(FromJSON a, Monad m) =>
Route -> RedditT m a
runRoute (Route -> RedditT m Empty) -> (a -> Route) -> a -> RedditT m Empty
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Route
forall a. Thing a => a -> Route
Route.readMessage

-- | Send a private message to another user.
sendMessage :: Monad m
            => Username -- ^ The username to send the message to
            -> Text -- ^ The subject of the message being sent
            -> Text -- ^ The body of the message being sent
            -> RedditT m ()
sendMessage :: Username -> Text -> Text -> RedditT m ()
sendMessage Username
u Text
s Text
b = RedditT m Empty -> RedditT m ()
forall (m :: * -> *). Monad m => m Empty -> m ()
nothing (RedditT m Empty -> RedditT m ())
-> RedditT m Empty -> RedditT m ()
forall a b. (a -> b) -> a -> b
$ Route -> RedditT m Empty
forall a (m :: * -> *).
(FromJSON a, Monad m) =>
Route -> RedditT m a
runRoute (Route -> RedditT m Empty) -> Route -> RedditT m Empty
forall a b. (a -> b) -> a -> b
$ Username -> Text -> Text -> Route
Route.sendMessage Username
u Text
s Text
b

-- | Send a private message (with a captcha).
sendMessageWithCaptcha :: Monad m
                       => Username -- ^ The username to send the message to
                       -> Text -- ^ The subject of the message being sent
                       -> Text -- ^ The body of the message being sent
                       -> CaptchaID -- ^ The identifier of the captcha being answered
                       -> Text -- ^ The answer to the specified captcha
                       -> RedditT m ()
sendMessageWithCaptcha :: Username -> Text -> Text -> CaptchaID -> Text -> RedditT m ()
sendMessageWithCaptcha Username
u Text
s Text
b CaptchaID
i Text
c = RedditT m Empty -> RedditT m ()
forall (m :: * -> *). Monad m => m Empty -> m ()
nothing (RedditT m Empty -> RedditT m ())
-> RedditT m Empty -> RedditT m ()
forall a b. (a -> b) -> a -> b
$ Route -> RedditT m Empty
forall a (m :: * -> *).
(FromJSON a, Monad m) =>
Route -> RedditT m a
runRoute (Route -> RedditT m Empty) -> Route -> RedditT m Empty
forall a b. (a -> b) -> a -> b
$ Username -> Text -> Text -> Route
Route.sendMessage Username
u Text
s Text
b Route -> (CaptchaID, Text) -> Route
`withCaptcha` (CaptchaID
i, Text
c)

-- | Reply to a message
replyMessage :: (Monad m, Thing a)
             => a -- ^ Thing to reply to
             -> Text -- ^ Response contents
             -> RedditT m MessageID
replyMessage :: a -> Text -> RedditT m MessageID
replyMessage a
t Text
b = do
  POSTWrapped MessageID
res <- Route -> RedditT m (POSTWrapped MessageID)
forall a (m :: * -> *).
(FromJSON a, Monad m) =>
Route -> RedditT m a
runRoute (Route -> RedditT m (POSTWrapped MessageID))
-> Route -> RedditT m (POSTWrapped MessageID)
forall a b. (a -> b) -> a -> b
$ a -> Text -> Route
forall a. Thing a => a -> Text -> Route
Route.reply a
t Text
b
  MessageID -> RedditT m MessageID
forall (m :: * -> *) a. Monad m => a -> m a
return MessageID
res