-- | A message from a channel
module Calamity.Types.Model.Channel.Message
    ( Message(..)
    , MessageType(..) ) where

import           Calamity.Internal.AesonThings
import           Calamity.Internal.Utils          ()
import           Calamity.Types.Model.Channel
import {-# SOURCE #-} Calamity.Types.Model.Guild.Guild
import           Calamity.Types.Model.Guild.Role
import           Calamity.Types.Model.User
import           Calamity.Types.Snowflake

import           Data.Aeson
import           Data.Scientific
import           Data.Text.Lazy                   ( Text )
import           Data.Time
import qualified Data.Vector.Unboxing             as UV

import           GHC.Generics

import           TextShow
import qualified TextShow.Generic                 as TSG

-- NOTE: make sure we fill in the guildID field when retrieving from REST
data Message = Message
  { Message -> Snowflake Message
id              :: Snowflake Message
  , Message -> Snowflake Channel
channelID       :: Snowflake Channel
  , Message -> Maybe (Snowflake Guild)
guildID         :: Maybe (Snowflake Guild)
  , Message -> Snowflake User
author          :: Snowflake User
  , Message -> Text
content         :: Text
  , Message -> UTCTime
timestamp       :: UTCTime
  , Message -> Maybe UTCTime
editedTimestamp :: Maybe UTCTime
  , Message -> Bool
tts             :: Bool
  , Message -> Bool
mentionEveryone :: Bool
  , Message -> Vector (Snowflake User)
mentions        :: UV.Vector (Snowflake User)
  , Message -> Vector (Snowflake Role)
mentionRoles    :: UV.Vector (Snowflake Role)
  , Message -> Maybe (Vector (Snowflake Channel))
mentionChannels :: Maybe (UV.Vector (Snowflake Channel))
  , Message -> [Attachment]
attachments     :: ![Attachment]
  , Message -> [Embed]
embeds          :: ![Embed]
  , Message -> [Reaction]
reactions       :: ![Reaction]
  , Message -> Maybe (Snowflake Message)
nonce           :: Maybe (Snowflake Message)
  , Message -> Bool
pinned          :: Bool
  , Message -> Maybe (Snowflake ())
webhookID       :: Maybe (Snowflake ())
  , Message -> MessageType
type_           :: !MessageType
  }
  deriving ( 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, 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, (forall x. Message -> Rep Message x)
-> (forall x. Rep Message x -> Message) -> Generic Message
forall x. Rep Message x -> Message
forall x. Message -> Rep Message x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep Message x -> Message
$cfrom :: forall x. Message -> Rep Message x
Generic )
  deriving ( Int -> Message -> Builder
Int -> Message -> Text
Int -> Message -> Text
[Message] -> Builder
[Message] -> Text
[Message] -> Text
Message -> Builder
Message -> Text
Message -> Text
(Int -> Message -> Builder)
-> (Message -> Builder)
-> ([Message] -> Builder)
-> (Int -> Message -> Text)
-> (Message -> Text)
-> ([Message] -> Text)
-> (Int -> Message -> Text)
-> (Message -> Text)
-> ([Message] -> Text)
-> TextShow Message
forall a.
(Int -> a -> Builder)
-> (a -> Builder)
-> ([a] -> Builder)
-> (Int -> a -> Text)
-> (a -> Text)
-> ([a] -> Text)
-> (Int -> a -> Text)
-> (a -> Text)
-> ([a] -> Text)
-> TextShow a
showtlList :: [Message] -> Text
$cshowtlList :: [Message] -> Text
showtl :: Message -> Text
$cshowtl :: Message -> Text
showtlPrec :: Int -> Message -> Text
$cshowtlPrec :: Int -> Message -> Text
showtList :: [Message] -> Text
$cshowtList :: [Message] -> Text
showt :: Message -> Text
$cshowt :: Message -> Text
showtPrec :: Int -> Message -> Text
$cshowtPrec :: Int -> Message -> Text
showbList :: [Message] -> Builder
$cshowbList :: [Message] -> Builder
showb :: Message -> Builder
$cshowb :: Message -> Builder
showbPrec :: Int -> Message -> Builder
$cshowbPrec :: Int -> Message -> Builder
TextShow ) via TSG.FromGeneric Message
  deriving ( Value -> Parser [Message]
Value -> Parser Message
(Value -> Parser Message)
-> (Value -> Parser [Message]) -> FromJSON Message
forall a.
(Value -> Parser a) -> (Value -> Parser [a]) -> FromJSON a
parseJSONList :: Value -> Parser [Message]
$cparseJSONList :: Value -> Parser [Message]
parseJSON :: Value -> Parser Message
$cparseJSON :: Value -> Parser Message
FromJSON ) via WithSpecialCases
      '["author" `ExtractFieldFrom` "id", "mentions" `ExtractArrayField` "id",
        "mention_channels" `ExtractArrayField` "id",
        "reactions" `IfNoneThen` DefaultToEmptyArray]
      Message
  deriving ( HasID Message ) via HasIDField "id" Message
  deriving ( HasID Channel ) via HasIDField "channelID" Message
  deriving ( HasID User ) via HasIDField "author" Message

-- Thanks sbrg (https://github.com/saevarb/haskord/blob/d1bb07bcc4f3dbc29f2dfd3351ff9f16fc100c07/haskord-lib/src/Haskord/Types/Common.hs#L264)
data MessageType
  = Default
  | RecipientAdd
  | RecipientRemove
  | Call
  | ChannelNameChange
  | ChannelIconChange
  | ChannelPinnedMessage
  | GuildMemberJoin
  | UserPremiumGuildSubscription
  | UserPremiumGuildSubscriptionTier1
  | UserPremiumGuildSubscriptionTier2
  | UserPremiumGuildSubscriptionTier3
  | ChannelFollowAdd
  | GuildDiscoveryDisqualified
  | GuildDiscoveryRequalified
  deriving ( MessageType -> MessageType -> Bool
(MessageType -> MessageType -> Bool)
-> (MessageType -> MessageType -> Bool) -> Eq MessageType
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: MessageType -> MessageType -> Bool
$c/= :: MessageType -> MessageType -> Bool
== :: MessageType -> MessageType -> Bool
$c== :: MessageType -> MessageType -> Bool
Eq, Int -> MessageType -> ShowS
[MessageType] -> ShowS
MessageType -> String
(Int -> MessageType -> ShowS)
-> (MessageType -> String)
-> ([MessageType] -> ShowS)
-> Show MessageType
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [MessageType] -> ShowS
$cshowList :: [MessageType] -> ShowS
show :: MessageType -> String
$cshow :: MessageType -> String
showsPrec :: Int -> MessageType -> ShowS
$cshowsPrec :: Int -> MessageType -> ShowS
Show, Int -> MessageType
MessageType -> Int
MessageType -> [MessageType]
MessageType -> MessageType
MessageType -> MessageType -> [MessageType]
MessageType -> MessageType -> MessageType -> [MessageType]
(MessageType -> MessageType)
-> (MessageType -> MessageType)
-> (Int -> MessageType)
-> (MessageType -> Int)
-> (MessageType -> [MessageType])
-> (MessageType -> MessageType -> [MessageType])
-> (MessageType -> MessageType -> [MessageType])
-> (MessageType -> MessageType -> MessageType -> [MessageType])
-> Enum MessageType
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
enumFromThenTo :: MessageType -> MessageType -> MessageType -> [MessageType]
$cenumFromThenTo :: MessageType -> MessageType -> MessageType -> [MessageType]
enumFromTo :: MessageType -> MessageType -> [MessageType]
$cenumFromTo :: MessageType -> MessageType -> [MessageType]
enumFromThen :: MessageType -> MessageType -> [MessageType]
$cenumFromThen :: MessageType -> MessageType -> [MessageType]
enumFrom :: MessageType -> [MessageType]
$cenumFrom :: MessageType -> [MessageType]
fromEnum :: MessageType -> Int
$cfromEnum :: MessageType -> Int
toEnum :: Int -> MessageType
$ctoEnum :: Int -> MessageType
pred :: MessageType -> MessageType
$cpred :: MessageType -> MessageType
succ :: MessageType -> MessageType
$csucc :: MessageType -> MessageType
Enum, (forall x. MessageType -> Rep MessageType x)
-> (forall x. Rep MessageType x -> MessageType)
-> Generic MessageType
forall x. Rep MessageType x -> MessageType
forall x. MessageType -> Rep MessageType x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep MessageType x -> MessageType
$cfrom :: forall x. MessageType -> Rep MessageType x
Generic )
  deriving ( Int -> MessageType -> Builder
Int -> MessageType -> Text
Int -> MessageType -> Text
[MessageType] -> Builder
[MessageType] -> Text
[MessageType] -> Text
MessageType -> Builder
MessageType -> Text
MessageType -> Text
(Int -> MessageType -> Builder)
-> (MessageType -> Builder)
-> ([MessageType] -> Builder)
-> (Int -> MessageType -> Text)
-> (MessageType -> Text)
-> ([MessageType] -> Text)
-> (Int -> MessageType -> Text)
-> (MessageType -> Text)
-> ([MessageType] -> Text)
-> TextShow MessageType
forall a.
(Int -> a -> Builder)
-> (a -> Builder)
-> ([a] -> Builder)
-> (Int -> a -> Text)
-> (a -> Text)
-> ([a] -> Text)
-> (Int -> a -> Text)
-> (a -> Text)
-> ([a] -> Text)
-> TextShow a
showtlList :: [MessageType] -> Text
$cshowtlList :: [MessageType] -> Text
showtl :: MessageType -> Text
$cshowtl :: MessageType -> Text
showtlPrec :: Int -> MessageType -> Text
$cshowtlPrec :: Int -> MessageType -> Text
showtList :: [MessageType] -> Text
$cshowtList :: [MessageType] -> Text
showt :: MessageType -> Text
$cshowt :: MessageType -> Text
showtPrec :: Int -> MessageType -> Text
$cshowtPrec :: Int -> MessageType -> Text
showbList :: [MessageType] -> Builder
$cshowbList :: [MessageType] -> Builder
showb :: MessageType -> Builder
$cshowb :: MessageType -> Builder
showbPrec :: Int -> MessageType -> Builder
$cshowbPrec :: Int -> MessageType -> Builder
TextShow ) via TSG.FromGeneric MessageType

instance FromJSON MessageType where
  parseJSON :: Value -> Parser MessageType
parseJSON = String
-> (Scientific -> Parser MessageType)
-> Value
-> Parser MessageType
forall a. String -> (Scientific -> Parser a) -> Value -> Parser a
withScientific String
"MessageType" ((Scientific -> Parser MessageType) -> Value -> Parser MessageType)
-> (Scientific -> Parser MessageType)
-> Value
-> Parser MessageType
forall a b. (a -> b) -> a -> b
$ \Scientific
n -> case Scientific -> Maybe Int
forall i. (Integral i, Bounded i) => Scientific -> Maybe i
toBoundedInteger @Int Scientific
n of
    Just !Int
v  -> case Int
v of
      Int
0 -> MessageType -> Parser MessageType
forall (f :: * -> *) a. Applicative f => a -> f a
pure MessageType
Default
      Int
1 -> MessageType -> Parser MessageType
forall (f :: * -> *) a. Applicative f => a -> f a
pure MessageType
RecipientAdd
      Int
2 -> MessageType -> Parser MessageType
forall (f :: * -> *) a. Applicative f => a -> f a
pure MessageType
RecipientRemove
      Int
3 -> MessageType -> Parser MessageType
forall (f :: * -> *) a. Applicative f => a -> f a
pure MessageType
Call
      Int
4 -> MessageType -> Parser MessageType
forall (f :: * -> *) a. Applicative f => a -> f a
pure MessageType
ChannelNameChange
      Int
5 -> MessageType -> Parser MessageType
forall (f :: * -> *) a. Applicative f => a -> f a
pure MessageType
ChannelIconChange
      Int
6 -> MessageType -> Parser MessageType
forall (f :: * -> *) a. Applicative f => a -> f a
pure MessageType
ChannelPinnedMessage
      Int
7 -> MessageType -> Parser MessageType
forall (f :: * -> *) a. Applicative f => a -> f a
pure MessageType
GuildMemberJoin
      Int
8 -> MessageType -> Parser MessageType
forall (f :: * -> *) a. Applicative f => a -> f a
pure MessageType
UserPremiumGuildSubscription
      Int
9 -> MessageType -> Parser MessageType
forall (f :: * -> *) a. Applicative f => a -> f a
pure MessageType
UserPremiumGuildSubscriptionTier1
      Int
10 -> MessageType -> Parser MessageType
forall (f :: * -> *) a. Applicative f => a -> f a
pure MessageType
UserPremiumGuildSubscriptionTier2
      Int
11 -> MessageType -> Parser MessageType
forall (f :: * -> *) a. Applicative f => a -> f a
pure MessageType
UserPremiumGuildSubscriptionTier3
      Int
12 -> MessageType -> Parser MessageType
forall (f :: * -> *) a. Applicative f => a -> f a
pure MessageType
ChannelFollowAdd
      Int
13 -> MessageType -> Parser MessageType
forall (f :: * -> *) a. Applicative f => a -> f a
pure MessageType
GuildDiscoveryDisqualified
      Int
14 -> MessageType -> Parser MessageType
forall (f :: * -> *) a. Applicative f => a -> f a
pure MessageType
GuildDiscoveryRequalified
      Int
_ -> String -> Parser MessageType
forall (m :: * -> *) a. MonadFail m => String -> m a
fail (String -> Parser MessageType) -> String -> Parser MessageType
forall a b. (a -> b) -> a -> b
$ String
"Invalid MessageType: " String -> ShowS
forall a. Semigroup a => a -> a -> a
<> Scientific -> String
forall a. Show a => a -> String
show Scientific
n
    Maybe Int
Nothing -> String -> Parser MessageType
forall (m :: * -> *) a. MonadFail m => String -> m a
fail (String -> Parser MessageType) -> String -> Parser MessageType
forall a b. (a -> b) -> a -> b
$ String
"Invalid MessageType: " String -> ShowS
forall a. Semigroup a => a -> a -> a
<> Scientific -> String
forall a. Show a => a -> String
show Scientific
n