{-# LANGUAGE TemplateHaskell #-}

-- | The generic channel type
module Calamity.Types.Model.Channel (
  Channel (..),
  Partial (PartialChannel),
  module Calamity.Types.Model.Channel.DM,
  module Calamity.Types.Model.Channel.Group,
  module Calamity.Types.Model.Channel.Guild,
  module Calamity.Types.Model.Channel.Attachment,
  module Calamity.Types.Model.Channel.Reaction,
  module Calamity.Types.Model.Channel.Webhook,
  module Calamity.Types.Model.Channel.Embed,
  module Calamity.Types.Model.Channel.ChannelType,
  module Calamity.Types.Model.Channel.Message,
  module Calamity.Types.Model.Channel.Component,
) where

import Calamity.Internal.Utils
import Calamity.Types.Model.Channel.Attachment
import Calamity.Types.Model.Channel.ChannelType
import Calamity.Types.Model.Channel.Component
import Calamity.Types.Model.Channel.DM
import Calamity.Types.Model.Channel.Embed
import Calamity.Types.Model.Channel.Group
import Calamity.Types.Model.Channel.Guild
import Calamity.Types.Model.Channel.Message
import Calamity.Types.Model.Channel.Reaction
import Calamity.Types.Model.Channel.Webhook
import Calamity.Types.Model.Guild.Permissions (Permissions)
import Calamity.Types.Snowflake
import Data.Aeson ((.:), (.:?))
import Data.Aeson qualified as Aeson
import Data.Text (Text)
import Optics.TH
import TextShow.TH

data Channel
  = DMChannel' DMChannel
  | GroupChannel' GroupChannel
  | GuildChannel' GuildChannel
  deriving (Int -> Channel -> ShowS
[Channel] -> ShowS
Channel -> String
(Int -> Channel -> ShowS)
-> (Channel -> String) -> ([Channel] -> ShowS) -> Show Channel
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Channel -> ShowS
showsPrec :: Int -> Channel -> ShowS
$cshow :: Channel -> String
show :: Channel -> String
$cshowList :: [Channel] -> ShowS
showList :: [Channel] -> ShowS
Show, Channel -> Channel -> Bool
(Channel -> Channel -> Bool)
-> (Channel -> Channel -> Bool) -> Eq Channel
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Channel -> Channel -> Bool
== :: Channel -> Channel -> Bool
$c/= :: Channel -> Channel -> Bool
/= :: Channel -> Channel -> Bool
Eq)

instance HasID Channel Channel where
  getID :: Channel -> Snowflake Channel
getID (DMChannel' DMChannel
a) = DMChannel -> Snowflake Channel
forall b a. HasID b a => a -> Snowflake b
getID DMChannel
a
  getID (GroupChannel' GroupChannel
a) = GroupChannel -> Snowflake Channel
forall b a. HasID b a => a -> Snowflake b
getID GroupChannel
a
  getID (GuildChannel' GuildChannel
a) = GuildChannel -> Snowflake Channel
forall b a. HasID b a => a -> Snowflake b
getID GuildChannel
a

instance Aeson.FromJSON Channel where
  parseJSON :: Value -> Parser Channel
parseJSON = String -> (Object -> Parser Channel) -> Value -> Parser Channel
forall a. String -> (Object -> Parser a) -> Value -> Parser a
Aeson.withObject String
"Channel" ((Object -> Parser Channel) -> Value -> Parser Channel)
-> (Object -> Parser Channel) -> Value -> Parser Channel
forall a b. (a -> b) -> a -> b
$ \Object
v -> do
    ChannelType
type_ <- Object
v Object -> Key -> Parser ChannelType
forall a. FromJSON a => Object -> Key -> Parser a
Aeson..: Key
"type"

    case ChannelType
type_ of
      ChannelType
GuildTextType -> GuildChannel -> Channel
GuildChannel' (GuildChannel -> Channel) -> Parser GuildChannel -> Parser Channel
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Value -> Parser GuildChannel
forall a. FromJSON a => Value -> Parser a
Aeson.parseJSON (Object -> Value
Aeson.Object Object
v)
      ChannelType
GuildVoiceType -> GuildChannel -> Channel
GuildChannel' (GuildChannel -> Channel) -> Parser GuildChannel -> Parser Channel
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Value -> Parser GuildChannel
forall a. FromJSON a => Value -> Parser a
Aeson.parseJSON (Object -> Value
Aeson.Object Object
v)
      ChannelType
GuildCategoryType -> GuildChannel -> Channel
GuildChannel' (GuildChannel -> Channel) -> Parser GuildChannel -> Parser Channel
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Value -> Parser GuildChannel
forall a. FromJSON a => Value -> Parser a
Aeson.parseJSON (Object -> Value
Aeson.Object Object
v)
      ChannelType
DMType -> DMChannel -> Channel
DMChannel' (DMChannel -> Channel) -> Parser DMChannel -> Parser Channel
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Value -> Parser DMChannel
forall a. FromJSON a => Value -> Parser a
Aeson.parseJSON (Object -> Value
Aeson.Object Object
v)
      ChannelType
GroupDMType -> GroupChannel -> Channel
GroupChannel' (GroupChannel -> Channel) -> Parser GroupChannel -> Parser Channel
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Value -> Parser GroupChannel
forall a. FromJSON a => Value -> Parser a
Aeson.parseJSON (Object -> Value
Aeson.Object Object
v)
      ChannelType
GuildNewsType -> GuildChannel -> Channel
GuildChannel' (GuildChannel -> Channel) -> Parser GuildChannel -> Parser Channel
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Value -> Parser GuildChannel
forall a. FromJSON a => Value -> Parser a
Aeson.parseJSON (Object -> Value
Aeson.Object Object
v)
      ChannelType
GuildNewsThreadType -> GuildChannel -> Channel
GuildChannel' (GuildChannel -> Channel) -> Parser GuildChannel -> Parser Channel
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Value -> Parser GuildChannel
forall a. FromJSON a => Value -> Parser a
Aeson.parseJSON (Object -> Value
Aeson.Object Object
v)
      ChannelType
GuildPublicThreadType -> GuildChannel -> Channel
GuildChannel' (GuildChannel -> Channel) -> Parser GuildChannel -> Parser Channel
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Value -> Parser GuildChannel
forall a. FromJSON a => Value -> Parser a
Aeson.parseJSON (Object -> Value
Aeson.Object Object
v)
      ChannelType
GuildPrivateThreadType -> GuildChannel -> Channel
GuildChannel' (GuildChannel -> Channel) -> Parser GuildChannel -> Parser Channel
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Value -> Parser GuildChannel
forall a. FromJSON a => Value -> Parser a
Aeson.parseJSON (Object -> Value
Aeson.Object Object
v)
      ChannelType
GuildStageVoiceType -> GuildChannel -> Channel
GuildChannel' (GuildChannel -> Channel) -> Parser GuildChannel -> Parser Channel
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Value -> Parser GuildChannel
forall a. FromJSON a => Value -> Parser a
Aeson.parseJSON (Object -> Value
Aeson.Object Object
v)
      ChannelType
GuildDirectoryType -> GuildChannel -> Channel
GuildChannel' (GuildChannel -> Channel) -> Parser GuildChannel -> Parser Channel
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Value -> Parser GuildChannel
forall a. FromJSON a => Value -> Parser a
Aeson.parseJSON (Object -> Value
Aeson.Object Object
v)
      ChannelType
GuildForumType -> GuildChannel -> Channel
GuildChannel' (GuildChannel -> Channel) -> Parser GuildChannel -> Parser Channel
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Value -> Parser GuildChannel
forall a. FromJSON a => Value -> Parser a
Aeson.parseJSON (Object -> Value
Aeson.Object Object
v)

data instance Partial Channel = PartialChannel
  { Partial Channel -> Snowflake Channel
id :: Snowflake Channel
  , Partial Channel -> Text
name :: Text
  , Partial Channel -> ChannelType
type_ :: ChannelType
  , Partial Channel -> Maybe Permissions
permissions :: Maybe Permissions
  , Partial Channel -> Maybe (Snowflake Category)
parentID :: Maybe (Snowflake Category)
  }
  deriving (Int -> Partial Channel -> ShowS
[Partial Channel] -> ShowS
Partial Channel -> String
(Int -> Partial Channel -> ShowS)
-> (Partial Channel -> String)
-> ([Partial Channel] -> ShowS)
-> Show (Partial Channel)
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Partial Channel -> ShowS
showsPrec :: Int -> Partial Channel -> ShowS
$cshow :: Partial Channel -> String
show :: Partial Channel -> String
$cshowList :: [Partial Channel] -> ShowS
showList :: [Partial Channel] -> ShowS
Show, Partial Channel -> Partial Channel -> Bool
(Partial Channel -> Partial Channel -> Bool)
-> (Partial Channel -> Partial Channel -> Bool)
-> Eq (Partial Channel)
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Partial Channel -> Partial Channel -> Bool
== :: Partial Channel -> Partial Channel -> Bool
$c/= :: Partial Channel -> Partial Channel -> Bool
/= :: Partial Channel -> Partial Channel -> Bool
Eq)
  deriving (HasID Channel) via HasIDField "id" (Partial Channel)
  deriving ([Partial Channel] -> Value
[Partial Channel] -> Encoding
Partial Channel -> Value
Partial Channel -> Encoding
(Partial Channel -> Value)
-> (Partial Channel -> Encoding)
-> ([Partial Channel] -> Value)
-> ([Partial Channel] -> Encoding)
-> ToJSON (Partial Channel)
forall a.
(a -> Value)
-> (a -> Encoding)
-> ([a] -> Value)
-> ([a] -> Encoding)
-> ToJSON a
$ctoJSON :: Partial Channel -> Value
toJSON :: Partial Channel -> Value
$ctoEncoding :: Partial Channel -> Encoding
toEncoding :: Partial Channel -> Encoding
$ctoJSONList :: [Partial Channel] -> Value
toJSONList :: [Partial Channel] -> Value
$ctoEncodingList :: [Partial Channel] -> Encoding
toEncodingList :: [Partial Channel] -> Encoding
Aeson.ToJSON) via CalamityToJSON (Partial Channel)

instance CalamityToJSON' (Partial Channel) where
  toPairs :: forall kv. KeyValue kv => Partial Channel -> [Maybe kv]
toPairs PartialChannel {Maybe Permissions
Maybe (Snowflake Category)
Text
ChannelType
Snowflake Channel
$sel:id:PartialChannel :: Partial Channel -> Snowflake Channel
$sel:name:PartialChannel :: Partial Channel -> Text
$sel:type_:PartialChannel :: Partial Channel -> ChannelType
$sel:permissions:PartialChannel :: Partial Channel -> Maybe Permissions
$sel:parentID:PartialChannel :: Partial Channel -> Maybe (Snowflake Category)
id :: Snowflake Channel
name :: Text
type_ :: ChannelType
permissions :: Maybe Permissions
parentID :: Maybe (Snowflake Category)
..} =
    [ Key
"id" Key -> Snowflake Channel -> Maybe kv
forall v kv. (ToJSON v, KeyValue kv) => Key -> v -> Maybe kv
.= Snowflake Channel
id
    , Key
"name" Key -> Text -> Maybe kv
forall v kv. (ToJSON v, KeyValue kv) => Key -> v -> Maybe kv
.= Text
name
    , Key
"type" Key -> ChannelType -> Maybe kv
forall v kv. (ToJSON v, KeyValue kv) => Key -> v -> Maybe kv
.= ChannelType
type_
    , Key
"permissions" Key -> Maybe Permissions -> Maybe kv
forall v kv. (ToJSON v, KeyValue kv) => Key -> Maybe v -> Maybe kv
.?= Maybe Permissions
permissions
    , Key
"parent_id" Key -> Maybe (Snowflake Category) -> Maybe kv
forall v kv. (ToJSON v, KeyValue kv) => Key -> Maybe v -> Maybe kv
.?= Maybe (Snowflake Category)
parentID
    ]

instance Aeson.FromJSON (Partial Channel) where
  parseJSON :: Value -> Parser (Partial Channel)
parseJSON = String
-> (Object -> Parser (Partial Channel))
-> Value
-> Parser (Partial Channel)
forall a. String -> (Object -> Parser a) -> Value -> Parser a
Aeson.withObject String
"Partial Channel" ((Object -> Parser (Partial Channel))
 -> Value -> Parser (Partial Channel))
-> (Object -> Parser (Partial Channel))
-> Value
-> Parser (Partial Channel)
forall a b. (a -> b) -> a -> b
$ \Object
v ->
    Snowflake Channel
-> Text
-> ChannelType
-> Maybe Permissions
-> Maybe (Snowflake Category)
-> Partial Channel
PartialChannel
      (Snowflake Channel
 -> Text
 -> ChannelType
 -> Maybe Permissions
 -> Maybe (Snowflake Category)
 -> Partial Channel)
-> Parser (Snowflake Channel)
-> Parser
     (Text
      -> ChannelType
      -> Maybe Permissions
      -> Maybe (Snowflake Category)
      -> Partial Channel)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object
v Object -> Key -> Parser (Snowflake Channel)
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"id"
      Parser
  (Text
   -> ChannelType
   -> Maybe Permissions
   -> Maybe (Snowflake Category)
   -> Partial Channel)
-> Parser Text
-> Parser
     (ChannelType
      -> Maybe Permissions
      -> Maybe (Snowflake Category)
      -> Partial Channel)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
v Object -> Key -> Parser Text
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"name"
      Parser
  (ChannelType
   -> Maybe Permissions
   -> Maybe (Snowflake Category)
   -> Partial Channel)
-> Parser ChannelType
-> Parser
     (Maybe Permissions
      -> Maybe (Snowflake Category) -> Partial Channel)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
v Object -> Key -> Parser ChannelType
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"type"
      Parser
  (Maybe Permissions
   -> Maybe (Snowflake Category) -> Partial Channel)
-> Parser (Maybe Permissions)
-> Parser (Maybe (Snowflake Category) -> Partial Channel)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
v Object -> Key -> Parser (Maybe Permissions)
forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"permissions"
      Parser (Maybe (Snowflake Category) -> Partial Channel)
-> Parser (Maybe (Snowflake Category)) -> Parser (Partial Channel)
forall a b. Parser (a -> b) -> Parser a -> Parser b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object
v Object -> Key -> Parser (Maybe (Snowflake Category))
forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"parent_id"

$(deriveTextShow ''Channel)
$(deriveTextShow 'PartialChannel)
$(makeFieldLabelsNoPrefix ''Channel)
$(makeFieldLabelsNoPrefix 'PartialChannel)