{-# LANGUAGE TemplateHaskell #-}

-- | Effect for handling the cache
module Calamity.Cache.Eff
    ( CacheEff(..)
    , setBotUser
    , updateBotUser
    , getBotUser
    , setGuild
    , updateGuild
    , getGuild
    , getGuildChannel
    , getGuilds
    , delGuild
    , setDM
    , updateDM
    , getDM
    , getDMs
    , delDM
      -- , setGuildChannel
      -- , getGuildChannel
      -- , delGuildChannel
    , setUser
    , updateUser
    , getUser
    , getUsers
    , delUser
    , setUnavailableGuild
    , isUnavailableGuild
    , getUnavailableGuilds
    , delUnavailableGuild
    , setMessage
    , updateMessage
    , getMessage
    , getMessages
    , delMessage ) where

import           Calamity.Internal.Utils
import           Calamity.Types.Model.Channel
import           Calamity.Types.Model.Guild
import           Calamity.Types.Model.User
import           Calamity.Types.Snowflake

import           Polysemy
import qualified Polysemy                     as P

data CacheEff m a where
  -- | Set the 'User' representing the bot itself
  SetBotUser :: User -> CacheEff m ()
  -- | Get the 'User' representing the bot itself
  GetBotUser :: CacheEff m (Maybe User)

  -- | Set or Update a 'Guild' in the cache
  SetGuild :: Guild -> CacheEff m ()
  -- | Get a 'Guild' from the cache
  GetGuild :: Snowflake Guild -> CacheEff m (Maybe Guild)
  -- | Get a 'GuildChannel' from the cache
  GetGuildChannel :: Snowflake GuildChannel -> CacheEff m (Maybe GuildChannel)
  -- | Get all 'Guild's from the cache
  GetGuilds :: CacheEff m [Guild]
  -- | Delete a 'Guild' from the cache
  DelGuild :: Snowflake Guild -> CacheEff m ()

  -- | Set or Update a 'DMChannel' in the cache
  SetDM :: DMChannel -> CacheEff m ()
  -- | Get a 'DMChannel' from the cache
  GetDM :: Snowflake DMChannel -> CacheEff m (Maybe DMChannel)
  -- | Get all 'DMChannel's from the cache
  GetDMs :: CacheEff m [DMChannel]
  -- | Delete a 'DMChannel' from the cache
  DelDM :: Snowflake DMChannel -> CacheEff m ()

  -- -- | Set or Update a 'GuildChannel' in the cache
  -- SetGuildChannel :: GuildChannel -> CacheEff m ()
  -- -- | Get a 'GuildChannel' from the cache
  -- GetGuildChannel :: Snowflake GuildChannel -> CacheEff m (Maybe GuildChannel)
  -- -- | Delete a 'GuildChannel' from the cache
  -- DelGuildChannel :: Snowflake GuildChannel -> CacheEff m ()
  -- | Set or Update a 'User' in the cache
  SetUser :: User -> CacheEff m ()
  -- | Get a 'User' from the cache
  GetUser :: Snowflake User -> CacheEff m (Maybe User)
  -- | Get all 'User's from the cache
  GetUsers :: CacheEff m [User]
  -- | Delete a 'User' from the cache
  DelUser :: Snowflake User -> CacheEff m ()

  -- | Flag a 'Guild' as unavailable
  SetUnavailableGuild :: Snowflake Guild -> CacheEff m ()
  -- | Test if a 'Guild' is flagged as unavailable
  IsUnavailableGuild :: Snowflake Guild -> CacheEff m Bool
  -- | Get all 'UnavailableGuild's from the cache
  GetUnavailableGuilds :: CacheEff m [Snowflake Guild]
  -- | Unflag a 'Guild' from being unavailable
  DelUnavailableGuild :: Snowflake Guild -> CacheEff m ()

  -- | Add or Update a 'Message' in the cache
  SetMessage :: Message -> CacheEff m ()
  -- | Get a 'Message' from the cache
  GetMessage :: Snowflake Message -> CacheEff m (Maybe Message)
  -- | Get all 'Message's from the cache
  GetMessages :: CacheEff m [Message]
  -- | Delete a 'Message' from the cache
  DelMessage :: Snowflake Message -> CacheEff m ()

makeSem ''CacheEff

updateBotUser :: P.Member CacheEff r => (User -> User) -> Sem r ()
updateBotUser :: (User -> User) -> Sem r ()
updateBotUser User -> User
f = Sem r (Maybe User)
forall (r :: EffectRow). Member CacheEff r => Sem r (Maybe User)
getBotUser Sem r (Maybe User) -> (Maybe User -> Sem r ()) -> Sem r ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (Maybe User -> (User -> Sem r ()) -> Sem r ())
-> (User -> Sem r ()) -> Maybe User -> Sem r ()
forall a b c. (a -> b -> c) -> b -> a -> c
flip Maybe User -> (User -> Sem r ()) -> Sem r ()
forall (m :: * -> *) a.
Applicative m =>
Maybe a -> (a -> m ()) -> m ()
whenJust (User -> Sem r ()
forall (r :: EffectRow). Member CacheEff r => User -> Sem r ()
setBotUser (User -> Sem r ()) -> (User -> User) -> User -> Sem r ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. User -> User
f)

updateGuild :: P.Member CacheEff r => Snowflake Guild -> (Guild -> Guild) -> Sem r ()
updateGuild :: Snowflake Guild -> (Guild -> Guild) -> Sem r ()
updateGuild Snowflake Guild
id Guild -> Guild
f = Snowflake Guild -> Sem r (Maybe Guild)
forall (r :: EffectRow).
Member CacheEff r =>
Snowflake Guild -> Sem r (Maybe Guild)
getGuild Snowflake Guild
id Sem r (Maybe Guild) -> (Maybe Guild -> Sem r ()) -> Sem r ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (Maybe Guild -> (Guild -> Sem r ()) -> Sem r ())
-> (Guild -> Sem r ()) -> Maybe Guild -> Sem r ()
forall a b c. (a -> b -> c) -> b -> a -> c
flip Maybe Guild -> (Guild -> Sem r ()) -> Sem r ()
forall (m :: * -> *) a.
Applicative m =>
Maybe a -> (a -> m ()) -> m ()
whenJust (Guild -> Sem r ()
forall (r :: EffectRow). Member CacheEff r => Guild -> Sem r ()
setGuild (Guild -> Sem r ()) -> (Guild -> Guild) -> Guild -> Sem r ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Guild -> Guild
f)

updateDM :: P.Member CacheEff r => Snowflake DMChannel -> (DMChannel -> DMChannel) -> Sem r ()
updateDM :: Snowflake DMChannel -> (DMChannel -> DMChannel) -> Sem r ()
updateDM Snowflake DMChannel
id DMChannel -> DMChannel
f = Snowflake DMChannel -> Sem r (Maybe DMChannel)
forall (r :: EffectRow).
Member CacheEff r =>
Snowflake DMChannel -> Sem r (Maybe DMChannel)
getDM Snowflake DMChannel
id Sem r (Maybe DMChannel)
-> (Maybe DMChannel -> Sem r ()) -> Sem r ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (Maybe DMChannel -> (DMChannel -> Sem r ()) -> Sem r ())
-> (DMChannel -> Sem r ()) -> Maybe DMChannel -> Sem r ()
forall a b c. (a -> b -> c) -> b -> a -> c
flip Maybe DMChannel -> (DMChannel -> Sem r ()) -> Sem r ()
forall (m :: * -> *) a.
Applicative m =>
Maybe a -> (a -> m ()) -> m ()
whenJust (DMChannel -> Sem r ()
forall (r :: EffectRow). Member CacheEff r => DMChannel -> Sem r ()
setDM (DMChannel -> Sem r ())
-> (DMChannel -> DMChannel) -> DMChannel -> Sem r ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. DMChannel -> DMChannel
f)

updateUser :: P.Member CacheEff r => Snowflake User -> (User -> User) -> Sem r ()
updateUser :: Snowflake User -> (User -> User) -> Sem r ()
updateUser Snowflake User
id User -> User
f = Snowflake User -> Sem r (Maybe User)
forall (r :: EffectRow).
Member CacheEff r =>
Snowflake User -> Sem r (Maybe User)
getUser Snowflake User
id Sem r (Maybe User) -> (Maybe User -> Sem r ()) -> Sem r ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (Maybe User -> (User -> Sem r ()) -> Sem r ())
-> (User -> Sem r ()) -> Maybe User -> Sem r ()
forall a b c. (a -> b -> c) -> b -> a -> c
flip Maybe User -> (User -> Sem r ()) -> Sem r ()
forall (m :: * -> *) a.
Applicative m =>
Maybe a -> (a -> m ()) -> m ()
whenJust (User -> Sem r ()
forall (r :: EffectRow). Member CacheEff r => User -> Sem r ()
setUser (User -> Sem r ()) -> (User -> User) -> User -> Sem r ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. User -> User
f)

updateMessage :: P.Member CacheEff r => Snowflake Message -> (Message -> Message) -> Sem r ()
updateMessage :: Snowflake Message -> (Message -> Message) -> Sem r ()
updateMessage Snowflake Message
id Message -> Message
f = Snowflake Message -> Sem r (Maybe Message)
forall (r :: EffectRow).
Member CacheEff r =>
Snowflake Message -> Sem r (Maybe Message)
getMessage Snowflake Message
id Sem r (Maybe Message) -> (Maybe Message -> Sem r ()) -> Sem r ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (Maybe Message -> (Message -> Sem r ()) -> Sem r ())
-> (Message -> Sem r ()) -> Maybe Message -> Sem r ()
forall a b c. (a -> b -> c) -> b -> a -> c
flip Maybe Message -> (Message -> Sem r ()) -> Sem r ()
forall (m :: * -> *) a.
Applicative m =>
Maybe a -> (a -> m ()) -> m ()
whenJust (Message -> Sem r ()
forall (r :: EffectRow). Member CacheEff r => Message -> Sem r ()
setMessage (Message -> Sem r ())
-> (Message -> Message) -> Message -> Sem r ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Message -> Message
f)