{-# LANGUAGE UnicodeSyntax #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE OverloadedStrings #-}

-- | Main handling entrypoint, other handlers are brached from here.
module MatrixBot.Bot.Jobs.Handlers.MainHandler
  ( jobsHandler
  ) where

import MatrixBot.Bot.BotM (BotM)
import qualified MatrixBot.MatrixApi.Client as Api
import Servant.Client.Core (AuthenticatedRequest)
import Servant.API (AuthProtect)
import MatrixBot.Bot.Jobs.Queue (HasBotJobsReader (botJobsReader))
import MatrixBot.Bot.Jobs.BotJob (BotJob (..))
import qualified MatrixBot.Log as L
import Control.Monad (forever)
import qualified UnliftIO.STM as STM
import Data.Text (pack)
import MatrixBot.Bot.Retry (retryOnClientError)
import Data.Functor (void)
import MatrixBot.Bot.Jobs.Handlers.SendReaction (sendReaction)
import MatrixBot.Bot.Jobs.Handlers.SendMessage (sendMessage)
import qualified Control.Lens as Lens


-- | Bot Jobs handler (infinite loop of reading new jobs and performing them)
jobsHandler
    r m
  . (BotM r m, HasBotJobsReader r)
   Api.MatrixApiClient
   AuthenticatedRequest (AuthProtect "access-token")
   m ()
jobsHandler :: forall r (m :: * -> *).
(BotM r m, HasBotJobsReader r) =>
MatrixApiClient
-> AuthenticatedRequest (AuthProtect "access-token") -> m ()
jobsHandler MatrixApiClient
req AuthenticatedRequest (AuthProtect "access-token")
auth = do
  Text -> m ()
forall (m :: * -> *). (MonadLogger m, HasCallStack) => Text -> m ()
L.logDebug Text
"Starting bot jobs queue handler…"

  forall (f :: * -> *) a b. Applicative f => f a -> f b
forever @m @() @() (m () -> m ()) -> m () -> m ()
forall a b. (a -> b) -> a -> b
$ do
    Text -> m ()
forall (m :: * -> *). (MonadLogger m, HasCallStack) => Text -> m ()
L.logDebug Text
"Waiting for next job to handle…"

    Getting (STM BotJob) r (STM BotJob) -> m (STM BotJob)
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
Lens.view Getting (STM BotJob) r (STM BotJob)
forall r. HasBotJobsReader r => Getter r (STM BotJob)
Getter r (STM BotJob)
botJobsReader
      m (STM BotJob) -> (STM BotJob -> m BotJob) -> m BotJob
forall a b. m a -> (a -> m b) -> m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= STM BotJob -> m BotJob
forall (m :: * -> *) a. MonadIO m => STM a -> m a
STM.atomically
      m BotJob -> (BotJob -> m BotJob) -> m BotJob
forall a b. m a -> (a -> m b) -> m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (\BotJob
x  BotJob
x BotJob -> m () -> m BotJob
forall a b. a -> m b -> m a
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ Text -> m ()
forall (m :: * -> *). (MonadLogger m, HasCallStack) => Text -> m ()
L.logDebug (Text
"Received a job to handle: " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> (String -> Text
pack (String -> Text) -> (BotJob -> String) -> BotJob -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. BotJob -> String
forall a. Show a => a -> String
show) BotJob
x))
      m BotJob -> (BotJob -> m ()) -> m ()
forall a b. m a -> (a -> m b) -> m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= m () -> m ()
forall (m :: * -> *) r a.
(MonadMask m, MonadLogger m, MonadIO m, MonadReader r m,
 HasRetryParams r) =>
m a -> m a
retryOnClientError (m () -> m ()) -> (BotJob -> m ()) -> BotJob -> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. \case
            BotJobSendReaction TransactionId
transactionId RoomId
roomId EventId
eventId Text
reactionText 
              m (Maybe EventResponse) -> m ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (m (Maybe EventResponse) -> m ())
-> m (Maybe EventResponse) -> m ()
forall a b. (a -> b) -> a -> b
$ MatrixApiClient
-> AuthenticatedRequest (AuthProtect "access-token")
-> TransactionId
-> RoomId
-> EventId
-> Text
-> m (Maybe EventResponse)
forall (m :: * -> *).
(MonadIO m, MonadFail m, MonadCatch m, MonadLogger m) =>
MatrixApiClient
-> AuthenticatedRequest (AuthProtect "access-token")
-> TransactionId
-> RoomId
-> EventId
-> Text
-> m (Maybe EventResponse)
sendReaction MatrixApiClient
req AuthenticatedRequest (AuthProtect "access-token")
auth TransactionId
transactionId RoomId
roomId EventId
eventId Text
reactionText
            BotJobSendMessage TransactionId
transactionId RoomId
roomId Maybe EventId
inReplyTo Maybe Text
htmlBody Text
msg 
              m EventResponse -> m ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (m EventResponse -> m ()) -> m EventResponse -> m ()
forall a b. (a -> b) -> a -> b
$ MatrixApiClient
-> AuthenticatedRequest (AuthProtect "access-token")
-> TransactionId
-> RoomId
-> Maybe EventId
-> Maybe Text
-> Text
-> Maybe MessageEdit
-> m EventResponse
forall (m :: * -> *).
(MonadIO m, MonadFail m, MonadThrow m, MonadLogger m) =>
MatrixApiClient
-> AuthenticatedRequest (AuthProtect "access-token")
-> TransactionId
-> RoomId
-> Maybe EventId
-> Maybe Text
-> Text
-> Maybe MessageEdit
-> m EventResponse
sendMessage MatrixApiClient
req AuthenticatedRequest (AuthProtect "access-token")
auth TransactionId
transactionId RoomId
roomId Maybe EventId
inReplyTo Maybe Text
htmlBody Text
msg Maybe MessageEdit
forall a. Maybe a
Nothing