{-# LANGUAGE TemplateHaskell #-}

-- | The generic guild channel type
module Calamity.Types.Model.Channel.Guild (
  GuildChannel (..),
  module Calamity.Types.Model.Channel.Guild.Category,
  module Calamity.Types.Model.Channel.Guild.Text,
  module Calamity.Types.Model.Channel.Guild.Voice,
) where

import {-# SOURCE #-} Calamity.Types.Model.Channel
import Calamity.Types.Model.Channel.ChannelType
import Calamity.Types.Model.Channel.Guild.Category
import Calamity.Types.Model.Channel.Guild.Text
import Calamity.Types.Model.Channel.Guild.Voice
import {-# SOURCE #-} Calamity.Types.Model.Guild.Guild
import Calamity.Types.Snowflake
import Data.Aeson ((.:))
import qualified Data.Aeson as Aeson
import Optics ((^.))
import Optics.TH
import TextShow.TH

data GuildChannel
  = GuildTextChannel TextChannel
  | GuildVoiceChannel VoiceChannel
  | GuildCategory Category
  | OtherGuildChannel (Snowflake Guild) (Snowflake GuildChannel) -- TODO
  deriving (Int -> GuildChannel -> ShowS
[GuildChannel] -> ShowS
GuildChannel -> String
(Int -> GuildChannel -> ShowS)
-> (GuildChannel -> String)
-> ([GuildChannel] -> ShowS)
-> Show GuildChannel
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [GuildChannel] -> ShowS
$cshowList :: [GuildChannel] -> ShowS
show :: GuildChannel -> String
$cshow :: GuildChannel -> String
showsPrec :: Int -> GuildChannel -> ShowS
$cshowsPrec :: Int -> GuildChannel -> ShowS
Show, GuildChannel -> GuildChannel -> Bool
(GuildChannel -> GuildChannel -> Bool)
-> (GuildChannel -> GuildChannel -> Bool) -> Eq GuildChannel
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: GuildChannel -> GuildChannel -> Bool
$c/= :: GuildChannel -> GuildChannel -> Bool
== :: GuildChannel -> GuildChannel -> Bool
$c== :: GuildChannel -> GuildChannel -> Bool
Eq)

instance Aeson.FromJSON GuildChannel where
  parseJSON :: Value -> Parser GuildChannel
parseJSON = String
-> (Object -> Parser GuildChannel) -> Value -> Parser GuildChannel
forall a. String -> (Object -> Parser a) -> Value -> Parser a
Aeson.withObject String
"GuildChannel" ((Object -> Parser GuildChannel) -> Value -> Parser GuildChannel)
-> (Object -> Parser GuildChannel) -> Value -> Parser GuildChannel
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
.: Key
"type"

    case ChannelType
type_ of
      ChannelType
GuildTextType -> TextChannel -> GuildChannel
GuildTextChannel (TextChannel -> GuildChannel)
-> Parser TextChannel -> Parser GuildChannel
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Value -> Parser TextChannel
forall a. FromJSON a => Value -> Parser a
Aeson.parseJSON (Object -> Value
Aeson.Object Object
v)
      ChannelType
GuildVoiceType -> VoiceChannel -> GuildChannel
GuildVoiceChannel (VoiceChannel -> GuildChannel)
-> Parser VoiceChannel -> Parser GuildChannel
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Value -> Parser VoiceChannel
forall a. FromJSON a => Value -> Parser a
Aeson.parseJSON (Object -> Value
Aeson.Object Object
v)
      ChannelType
GuildCategoryType -> Category -> GuildChannel
GuildCategory (Category -> GuildChannel)
-> Parser Category -> Parser GuildChannel
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Value -> Parser Category
forall a. FromJSON a => Value -> Parser a
Aeson.parseJSON (Object -> Value
Aeson.Object Object
v)
      ChannelType
_typ -> do
        Snowflake GuildChannel
id_ <- Object
v Object -> Key -> Parser (Snowflake GuildChannel)
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"id"
        Snowflake Guild
guildID <- Object
v Object -> Key -> Parser (Snowflake Guild)
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"guild_id"
        GuildChannel -> Parser GuildChannel
forall (f :: * -> *) a. Applicative f => a -> f a
pure (GuildChannel -> Parser GuildChannel)
-> GuildChannel -> Parser GuildChannel
forall a b. (a -> b) -> a -> b
$ Snowflake Guild -> Snowflake GuildChannel -> GuildChannel
OtherGuildChannel Snowflake Guild
guildID Snowflake GuildChannel
id_

instance HasID GuildChannel GuildChannel where
  getID :: GuildChannel -> Snowflake GuildChannel
getID (GuildTextChannel TextChannel
a) = Snowflake TextChannel -> Snowflake GuildChannel
forall a b. Snowflake a -> Snowflake b
coerceSnowflake (Snowflake TextChannel -> Snowflake GuildChannel)
-> Snowflake TextChannel -> Snowflake GuildChannel
forall a b. (a -> b) -> a -> b
$ TextChannel
a TextChannel
-> Optic' A_Lens NoIx TextChannel (Snowflake TextChannel)
-> Snowflake TextChannel
forall k s (is :: IxList) a.
Is k A_Getter =>
s -> Optic' k is s a -> a
^. Optic' A_Lens NoIx TextChannel (Snowflake TextChannel)
#id
  getID (GuildVoiceChannel VoiceChannel
a) = Snowflake VoiceChannel -> Snowflake GuildChannel
forall a b. Snowflake a -> Snowflake b
coerceSnowflake (Snowflake VoiceChannel -> Snowflake GuildChannel)
-> Snowflake VoiceChannel -> Snowflake GuildChannel
forall a b. (a -> b) -> a -> b
$ VoiceChannel
a VoiceChannel
-> Optic' A_Lens NoIx VoiceChannel (Snowflake VoiceChannel)
-> Snowflake VoiceChannel
forall k s (is :: IxList) a.
Is k A_Getter =>
s -> Optic' k is s a -> a
^. Optic' A_Lens NoIx VoiceChannel (Snowflake VoiceChannel)
#id
  getID (GuildCategory Category
a) = Snowflake Category -> Snowflake GuildChannel
forall a b. Snowflake a -> Snowflake b
coerceSnowflake (Snowflake Category -> Snowflake GuildChannel)
-> Snowflake Category -> Snowflake GuildChannel
forall a b. (a -> b) -> a -> b
$ Category
a Category
-> Optic' A_Lens NoIx Category (Snowflake Category)
-> Snowflake Category
forall k s (is :: IxList) a.
Is k A_Getter =>
s -> Optic' k is s a -> a
^. Optic' A_Lens NoIx Category (Snowflake Category)
#id
  getID (OtherGuildChannel Snowflake Guild
_ Snowflake GuildChannel
a) = Snowflake GuildChannel
a

instance HasID Channel GuildChannel where
  getID :: GuildChannel -> Snowflake Channel
getID = Snowflake GuildChannel -> Snowflake Channel
forall a b. Snowflake a -> Snowflake b
coerceSnowflake (Snowflake GuildChannel -> Snowflake Channel)
-> (GuildChannel -> Snowflake GuildChannel)
-> GuildChannel
-> Snowflake Channel
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall b a. HasID b a => a -> Snowflake b
getID @GuildChannel

instance HasID Guild GuildChannel where
  getID :: GuildChannel -> Snowflake Guild
getID (GuildTextChannel TextChannel
a) = Snowflake Guild -> Snowflake Guild
forall a b. Snowflake a -> Snowflake b
coerceSnowflake (Snowflake Guild -> Snowflake Guild)
-> Snowflake Guild -> Snowflake Guild
forall a b. (a -> b) -> a -> b
$ TextChannel
a TextChannel
-> Optic' A_Lens NoIx TextChannel (Snowflake Guild)
-> Snowflake Guild
forall k s (is :: IxList) a.
Is k A_Getter =>
s -> Optic' k is s a -> a
^. Optic' A_Lens NoIx TextChannel (Snowflake Guild)
#guildID
  getID (GuildVoiceChannel VoiceChannel
a) = Snowflake Guild -> Snowflake Guild
forall a b. Snowflake a -> Snowflake b
coerceSnowflake (Snowflake Guild -> Snowflake Guild)
-> Snowflake Guild -> Snowflake Guild
forall a b. (a -> b) -> a -> b
$ VoiceChannel
a VoiceChannel
-> Optic' A_Lens NoIx VoiceChannel (Snowflake Guild)
-> Snowflake Guild
forall k s (is :: IxList) a.
Is k A_Getter =>
s -> Optic' k is s a -> a
^. Optic' A_Lens NoIx VoiceChannel (Snowflake Guild)
#guildID
  getID (GuildCategory Category
a) = Snowflake Guild -> Snowflake Guild
forall a b. Snowflake a -> Snowflake b
coerceSnowflake (Snowflake Guild -> Snowflake Guild)
-> Snowflake Guild -> Snowflake Guild
forall a b. (a -> b) -> a -> b
$ Category
a Category
-> Optic' A_Lens NoIx Category (Snowflake Guild) -> Snowflake Guild
forall k s (is :: IxList) a.
Is k A_Getter =>
s -> Optic' k is s a -> a
^. Optic' A_Lens NoIx Category (Snowflake Guild)
#guildID
  getID (OtherGuildChannel Snowflake Guild
a Snowflake GuildChannel
_) = Snowflake Guild
a

$(deriveTextShow ''GuildChannel)
$(makeFieldLabelsNoPrefix ''GuildChannel)