module Reddit.Types.Message where

import Reddit.Parser
import Reddit.Types.Comment
import Reddit.Types.Listing
import Reddit.Types.Reddit
import Reddit.Types.Thing
import Reddit.Types.User
import Reddit.Utilities

import Control.Applicative
import Data.Aeson
import Data.Maybe
import Data.Monoid
import Data.Text (Text)
import Network.API.Builder.Query
import Prelude
import qualified Data.Vector as Vector

data Message = Message { Message -> MessageKind
messageID :: MessageKind
                       , Message -> Bool
new :: Bool
                       , Message -> Username
to :: Username
                       , Message -> Maybe Username
from :: Maybe Username
                       , Message -> Text
subject :: Text
                       , Message -> Text
body :: Text
                       , Message -> Text
bodyHTML :: Text
                       , Message -> Listing MessageKind Message
replies :: Listing MessageKind Message }
  deriving (Int -> Message -> ShowS
[Message] -> ShowS
Message -> String
(Int -> Message -> ShowS)
-> (Message -> String) -> ([Message] -> ShowS) -> Show Message
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Message] -> ShowS
$cshowList :: [Message] -> ShowS
show :: Message -> String
$cshow :: Message -> String
showsPrec :: Int -> Message -> ShowS
$cshowsPrec :: Int -> Message -> ShowS
Show, ReadPrec [Message]
ReadPrec Message
Int -> ReadS Message
ReadS [Message]
(Int -> ReadS Message)
-> ReadS [Message]
-> ReadPrec Message
-> ReadPrec [Message]
-> Read Message
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [Message]
$creadListPrec :: ReadPrec [Message]
readPrec :: ReadPrec Message
$creadPrec :: ReadPrec Message
readList :: ReadS [Message]
$creadList :: ReadS [Message]
readsPrec :: Int -> ReadS Message
$creadsPrec :: Int -> ReadS Message
Read, Message -> Message -> Bool
(Message -> Message -> Bool)
-> (Message -> Message -> Bool) -> Eq Message
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Message -> Message -> Bool
$c/= :: Message -> Message -> Bool
== :: Message -> Message -> Bool
$c== :: Message -> Message -> Bool
Eq)

instance FromJSON Message where
  parseJSON :: Value -> Parser Message
parseJSON (Object Object
o) = do
    Object
d <- Object
o Object -> Key -> Parser Object
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"data"
    MessageKind
-> Bool
-> Username
-> Maybe Username
-> Text
-> Text
-> Text
-> Listing MessageKind Message
-> Message
Message (MessageKind
 -> Bool
 -> Username
 -> Maybe Username
 -> Text
 -> Text
 -> Text
 -> Listing MessageKind Message
 -> Message)
-> Parser MessageKind
-> Parser
     (Bool
      -> Username
      -> Maybe Username
      -> Text
      -> Text
      -> Text
      -> Listing MessageKind Message
      -> Message)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
d Object -> Key -> Parser MessageKind
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"name"
            Parser
  (Bool
   -> Username
   -> Maybe Username
   -> Text
   -> Text
   -> Text
   -> Listing MessageKind Message
   -> Message)
-> Parser Bool
-> Parser
     (Username
      -> Maybe Username
      -> Text
      -> Text
      -> Text
      -> Listing MessageKind Message
      -> Message)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
d Object -> Key -> Parser Bool
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"new"
            Parser
  (Username
   -> Maybe Username
   -> Text
   -> Text
   -> Text
   -> Listing MessageKind Message
   -> Message)
-> Parser Username
-> Parser
     (Maybe Username
      -> Text -> Text -> Text -> Listing MessageKind Message -> Message)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
d Object -> Key -> Parser Username
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"dest"
            Parser
  (Maybe Username
   -> Text -> Text -> Text -> Listing MessageKind Message -> Message)
-> Parser (Maybe Username)
-> Parser
     (Text -> Text -> Text -> Listing MessageKind Message -> Message)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
d Object -> Key -> Parser (Maybe Username)
forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"author"
            Parser
  (Text -> Text -> Text -> Listing MessageKind Message -> Message)
-> Parser Text
-> Parser (Text -> Text -> Listing MessageKind Message -> Message)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> (Object
d Object -> Key -> Parser Text
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"link_title" Parser Text -> Parser Text -> Parser Text
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Object
d Object -> Key -> Parser Text
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"subject")
            Parser (Text -> Text -> Listing MessageKind Message -> Message)
-> Parser Text
-> Parser (Text -> Listing MessageKind Message -> Message)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> (Text -> Text
unescape (Text -> Text) -> Parser Text -> Parser Text
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
d Object -> Key -> Parser Text
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"body")
            Parser (Text -> Listing MessageKind Message -> Message)
-> Parser Text -> Parser (Listing MessageKind Message -> Message)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> (Text -> Text
unescape (Text -> Text) -> Parser Text -> Parser Text
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
d Object -> Key -> Parser Text
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"body_html")
            Parser (Listing MessageKind Message -> Message)
-> Parser (Listing MessageKind Message) -> Parser Message
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> (Listing MessageKind Message
-> Maybe (Listing MessageKind Message)
-> Listing MessageKind Message
forall a. a -> Maybe a -> a
fromMaybe (Maybe MessageKind
-> Maybe MessageKind -> [Message] -> Listing MessageKind Message
forall t a. Maybe t -> Maybe t -> [a] -> Listing t a
Listing Maybe MessageKind
forall a. Maybe a
Nothing Maybe MessageKind
forall a. Maybe a
Nothing []) (Maybe (Listing MessageKind Message)
 -> Listing MessageKind Message)
-> Parser (Maybe (Listing MessageKind Message))
-> Parser (Listing MessageKind Message)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
d Object -> Key -> Parser (Maybe (Listing MessageKind Message))
forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"replies")
  parseJSON Value
_ = Parser Message
forall a. Monoid a => a
mempty

instance Thing Message where
  fullName :: Message -> Text
fullName Message
m = MessageKind -> Text
forall a. Thing a => a -> Text
fullName (MessageKind -> Text) -> MessageKind -> Text
forall a b. (a -> b) -> a -> b
$ Message -> MessageKind
messageID Message
m

instance ToQuery Message where
  toQuery :: Text -> Message -> [(Text, Text)]
toQuery Text
k Message
v = [(Text
k, Message -> Text
forall a. Thing a => a -> Text
fullName Message
v)]

isPrivateMessage :: Message -> Bool
isPrivateMessage :: Message -> Bool
isPrivateMessage Message
m =
  case Message -> MessageKind
messageID Message
m of
    PrivateMessage MessageID
_ -> Bool
True
    MessageKind
_ -> Bool
False

isCommentReply :: Message -> Bool
isCommentReply :: Message -> Bool
isCommentReply Message
m =
  case Message -> MessageKind
messageID Message
m of
    CommentMessage CommentID
_ -> Bool
True
    MessageKind
_ -> Bool
False

data MessageID = MessageID Text
  deriving (Int -> MessageID -> ShowS
[MessageID] -> ShowS
MessageID -> String
(Int -> MessageID -> ShowS)
-> (MessageID -> String)
-> ([MessageID] -> ShowS)
-> Show MessageID
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [MessageID] -> ShowS
$cshowList :: [MessageID] -> ShowS
show :: MessageID -> String
$cshow :: MessageID -> String
showsPrec :: Int -> MessageID -> ShowS
$cshowsPrec :: Int -> MessageID -> ShowS
Show, ReadPrec [MessageID]
ReadPrec MessageID
Int -> ReadS MessageID
ReadS [MessageID]
(Int -> ReadS MessageID)
-> ReadS [MessageID]
-> ReadPrec MessageID
-> ReadPrec [MessageID]
-> Read MessageID
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [MessageID]
$creadListPrec :: ReadPrec [MessageID]
readPrec :: ReadPrec MessageID
$creadPrec :: ReadPrec MessageID
readList :: ReadS [MessageID]
$creadList :: ReadS [MessageID]
readsPrec :: Int -> ReadS MessageID
$creadsPrec :: Int -> ReadS MessageID
Read, MessageID -> MessageID -> Bool
(MessageID -> MessageID -> Bool)
-> (MessageID -> MessageID -> Bool) -> Eq MessageID
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: MessageID -> MessageID -> Bool
$c/= :: MessageID -> MessageID -> Bool
== :: MessageID -> MessageID -> Bool
$c== :: MessageID -> MessageID -> Bool
Eq, Eq MessageID
Eq MessageID
-> (MessageID -> MessageID -> Ordering)
-> (MessageID -> MessageID -> Bool)
-> (MessageID -> MessageID -> Bool)
-> (MessageID -> MessageID -> Bool)
-> (MessageID -> MessageID -> Bool)
-> (MessageID -> MessageID -> MessageID)
-> (MessageID -> MessageID -> MessageID)
-> Ord MessageID
MessageID -> MessageID -> Bool
MessageID -> MessageID -> Ordering
MessageID -> MessageID -> MessageID
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: MessageID -> MessageID -> MessageID
$cmin :: MessageID -> MessageID -> MessageID
max :: MessageID -> MessageID -> MessageID
$cmax :: MessageID -> MessageID -> MessageID
>= :: MessageID -> MessageID -> Bool
$c>= :: MessageID -> MessageID -> Bool
> :: MessageID -> MessageID -> Bool
$c> :: MessageID -> MessageID -> Bool
<= :: MessageID -> MessageID -> Bool
$c<= :: MessageID -> MessageID -> Bool
< :: MessageID -> MessageID -> Bool
$c< :: MessageID -> MessageID -> Bool
compare :: MessageID -> MessageID -> Ordering
$ccompare :: MessageID -> MessageID -> Ordering
$cp1Ord :: Eq MessageID
Ord)

instance FromJSON MessageID where
  parseJSON :: Value -> Parser MessageID
parseJSON (String Text
s) =
    Text -> MessageID
MessageID (Text -> MessageID) -> Parser Text -> Parser MessageID
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Text -> Text -> Parser Text
stripPrefix Text
messagePrefix Text
s
  parseJSON Value
_ = Parser MessageID
forall a. Monoid a => a
mempty

instance Thing MessageID where
  fullName :: MessageID -> Text
fullName (MessageID Text
m) = [Text] -> Text
forall a. Monoid a => [a] -> a
mconcat [Text
messagePrefix, Text
"_", Text
m]

instance ToQuery MessageID where
  toQuery :: Text -> MessageID -> [(Text, Text)]
toQuery Text
k MessageID
m = Text -> Text -> [(Text, Text)]
forall a. ToQuery a => Text -> a -> [(Text, Text)]
toQuery Text
k (MessageID -> Text
forall a. Thing a => a -> Text
fullName MessageID
m)

instance FromJSON (POSTWrapped MessageID) where
  parseJSON :: Value -> Parser (POSTWrapped MessageID)
parseJSON (Object Object
o) = do
    Vector Object
ms <- (Object
o Object -> Key -> Parser Object
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"json") Parser Object -> (Object -> Parser Object) -> Parser Object
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (Object -> Key -> Parser Object
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"data") Parser Object
-> (Object -> Parser (Vector Object)) -> Parser (Vector Object)
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (Object -> Key -> Parser (Vector Object)
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"things")
    case Vector Object -> [Object]
forall a. Vector a -> [a]
Vector.toList Vector Object
ms of
      [Object
v] -> MessageID -> POSTWrapped MessageID
forall a. a -> POSTWrapped a
POSTWrapped (MessageID -> POSTWrapped MessageID)
-> Parser MessageID -> Parser (POSTWrapped MessageID)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Object
v Object -> Key -> Parser Object
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"data" Parser Object -> (Object -> Parser MessageID) -> Parser MessageID
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (Object -> Key -> Parser MessageID
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"id"))
      [Object]
_ -> Parser (POSTWrapped MessageID)
forall a. Monoid a => a
mempty
  parseJSON Value
_ = Parser (POSTWrapped MessageID)
forall a. Monoid a => a
mempty

messagePrefix :: Text
messagePrefix :: Text
messagePrefix = Text
"t4"

data MessageKind = CommentMessage CommentID
                 | PrivateMessage MessageID
  deriving (Int -> MessageKind -> ShowS
[MessageKind] -> ShowS
MessageKind -> String
(Int -> MessageKind -> ShowS)
-> (MessageKind -> String)
-> ([MessageKind] -> ShowS)
-> Show MessageKind
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [MessageKind] -> ShowS
$cshowList :: [MessageKind] -> ShowS
show :: MessageKind -> String
$cshow :: MessageKind -> String
showsPrec :: Int -> MessageKind -> ShowS
$cshowsPrec :: Int -> MessageKind -> ShowS
Show, ReadPrec [MessageKind]
ReadPrec MessageKind
Int -> ReadS MessageKind
ReadS [MessageKind]
(Int -> ReadS MessageKind)
-> ReadS [MessageKind]
-> ReadPrec MessageKind
-> ReadPrec [MessageKind]
-> Read MessageKind
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [MessageKind]
$creadListPrec :: ReadPrec [MessageKind]
readPrec :: ReadPrec MessageKind
$creadPrec :: ReadPrec MessageKind
readList :: ReadS [MessageKind]
$creadList :: ReadS [MessageKind]
readsPrec :: Int -> ReadS MessageKind
$creadsPrec :: Int -> ReadS MessageKind
Read, MessageKind -> MessageKind -> Bool
(MessageKind -> MessageKind -> Bool)
-> (MessageKind -> MessageKind -> Bool) -> Eq MessageKind
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: MessageKind -> MessageKind -> Bool
$c/= :: MessageKind -> MessageKind -> Bool
== :: MessageKind -> MessageKind -> Bool
$c== :: MessageKind -> MessageKind -> Bool
Eq, Eq MessageKind
Eq MessageKind
-> (MessageKind -> MessageKind -> Ordering)
-> (MessageKind -> MessageKind -> Bool)
-> (MessageKind -> MessageKind -> Bool)
-> (MessageKind -> MessageKind -> Bool)
-> (MessageKind -> MessageKind -> Bool)
-> (MessageKind -> MessageKind -> MessageKind)
-> (MessageKind -> MessageKind -> MessageKind)
-> Ord MessageKind
MessageKind -> MessageKind -> Bool
MessageKind -> MessageKind -> Ordering
MessageKind -> MessageKind -> MessageKind
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: MessageKind -> MessageKind -> MessageKind
$cmin :: MessageKind -> MessageKind -> MessageKind
max :: MessageKind -> MessageKind -> MessageKind
$cmax :: MessageKind -> MessageKind -> MessageKind
>= :: MessageKind -> MessageKind -> Bool
$c>= :: MessageKind -> MessageKind -> Bool
> :: MessageKind -> MessageKind -> Bool
$c> :: MessageKind -> MessageKind -> Bool
<= :: MessageKind -> MessageKind -> Bool
$c<= :: MessageKind -> MessageKind -> Bool
< :: MessageKind -> MessageKind -> Bool
$c< :: MessageKind -> MessageKind -> Bool
compare :: MessageKind -> MessageKind -> Ordering
$ccompare :: MessageKind -> MessageKind -> Ordering
$cp1Ord :: Eq MessageKind
Ord)

instance FromJSON MessageKind where
  parseJSON :: Value -> Parser MessageKind
parseJSON Value
s =
    (CommentID -> MessageKind
CommentMessage (CommentID -> MessageKind)
-> Parser CommentID -> Parser MessageKind
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Value -> Parser CommentID
forall a. FromJSON a => Value -> Parser a
parseJSON Value
s) Parser MessageKind -> Parser MessageKind -> Parser MessageKind
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|>
    (MessageID -> MessageKind
PrivateMessage (MessageID -> MessageKind)
-> Parser MessageID -> Parser MessageKind
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Value -> Parser MessageID
forall a. FromJSON a => Value -> Parser a
parseJSON Value
s)

instance Thing MessageKind where
  fullName :: MessageKind -> Text
fullName (CommentMessage CommentID
c) = CommentID -> Text
forall a. Thing a => a -> Text
fullName CommentID
c
  fullName (PrivateMessage MessageID
p) = MessageID -> Text
forall a. Thing a => a -> Text
fullName MessageID
p

instance ToQuery MessageKind where
  toQuery :: Text -> MessageKind -> [(Text, Text)]
toQuery Text
k (CommentMessage CommentID
c) = Text -> CommentID -> [(Text, Text)]
forall a. ToQuery a => Text -> a -> [(Text, Text)]
toQuery Text
k CommentID
c
  toQuery Text
k (PrivateMessage MessageID
p) = Text -> MessageID -> [(Text, Text)]
forall a. ToQuery a => Text -> a -> [(Text, Text)]
toQuery Text
k MessageID
p