-- | This module provides a service for custom alerts.
module Navi.Services.Custom
  ( CustomToml,
    toEvent,
  )
where

import Data.List.NonEmpty qualified as NE
import Data.Map.Strict qualified as Map
import Data.Text qualified as T
import Navi.Data.CommandResult (CommandResult (MkCommandResult))
import Navi.Data.CommandResultParser
  ( CommandResultParserToml (MkCommandResultParserToml),
    defaultParser,
  )
import Navi.Data.NaviNote (NaviNote, replaceOut)
import Navi.Data.PollInterval (PollInterval (MkPollInterval))
import Navi.Event.Toml qualified as EventToml
import Navi.Event.Types
  ( AnyEvent (MkAnyEvent),
    ErrorNote,
    Event
      ( MkEvent,
        errorNote,
        name,
        pollInterval,
        raiseAlert,
        repeatEvent,
        serviceType
      ),
    RepeatEvent,
  )
import Navi.Prelude
import Navi.Services.Custom.Toml
  ( CustomToml,
    TriggerNoteToml (MkTriggerNoteToml),
  )
import Navi.Services.Types (ServiceType (Custom))
import Pythia.Data.Command (Command)

-- | Transforms toml configuration data into an 'AnyEvent'.
toEvent :: (MonadIORef m) => CustomToml -> m AnyEvent
toEvent :: forall (m :: Type -> Type).
MonadIORef m =>
CustomToml -> m AnyEvent
toEvent CustomToml
toml = do
  RepeatEvent CommandResult
repeatEvent <- (Text -> CommandResult)
-> Maybe (MultiRepeatEventToml Text)
-> m (RepeatEvent CommandResult)
forall (m :: Type -> Type) b a.
(MonadIORef m, Ord b) =>
(a -> b) -> Maybe (MultiRepeatEventToml a) -> m (RepeatEvent b)
EventToml.mMultiRepeatEventTomlToVal Text -> CommandResult
toCommandResult (CustomToml
toml CustomToml
-> Optic'
     A_Lens NoIx CustomToml (Maybe (MultiRepeatEventToml Text))
-> Maybe (MultiRepeatEventToml Text)
forall k s (is :: IxList) a.
Is k A_Getter =>
s -> Optic' k is s a -> a
^. Optic' A_Lens NoIx CustomToml (Maybe (MultiRepeatEventToml Text))
#repeatEventCfg)
  ErrorNote
errorNote <- Maybe ErrorNoteToml -> m ErrorNote
forall (m :: Type -> Type).
MonadIORef m =>
Maybe ErrorNoteToml -> m ErrorNote
EventToml.mErrorNoteTomlToVal (CustomToml
toml CustomToml
-> Optic' A_Lens NoIx CustomToml (Maybe ErrorNoteToml)
-> Maybe ErrorNoteToml
forall k s (is :: IxList) a.
Is k A_Getter =>
s -> Optic' k is s a -> a
^. Optic' A_Lens NoIx CustomToml (Maybe ErrorNoteToml)
#errEventCfg)
  pure
    $ Event CommandResult CommandResult -> AnyEvent
forall trigger result.
(Ord trigger, Show result, Show trigger) =>
Event result trigger -> AnyEvent
MkAnyEvent
    (Event CommandResult CommandResult -> AnyEvent)
-> Event CommandResult CommandResult -> AnyEvent
forall a b. (a -> b) -> a -> b
$ Maybe Text
-> Command
-> NonEmpty (Text, NaviNote)
-> PollInterval
-> RepeatEvent CommandResult
-> ErrorNote
-> Maybe CommandResultParserToml
-> Event CommandResult CommandResult
mkCustomEvent
      (CustomToml
toml CustomToml
-> Optic' A_Lens NoIx CustomToml (Maybe Text) -> Maybe Text
forall k s (is :: IxList) a.
Is k A_Getter =>
s -> Optic' k is s a -> a
^. Optic' A_Lens NoIx CustomToml (Maybe Text)
#name)
      (CustomToml
toml CustomToml -> Optic' A_Lens NoIx CustomToml Command -> Command
forall k s (is :: IxList) a.
Is k A_Getter =>
s -> Optic' k is s a -> a
^. Optic' A_Lens NoIx CustomToml Command
#command)
      NonEmpty (Text, NaviNote)
triggerNotePairs
      PollInterval
pi
      RepeatEvent CommandResult
repeatEvent
      ErrorNote
errorNote
      (CustomToml
toml CustomToml
-> Optic' A_Lens NoIx CustomToml (Maybe CommandResultParserToml)
-> Maybe CommandResultParserToml
forall k s (is :: IxList) a.
Is k A_Getter =>
s -> Optic' k is s a -> a
^. Optic' A_Lens NoIx CustomToml (Maybe CommandResultParserToml)
#parser)
  where
    triggerNotePairs :: NonEmpty (Text, NaviNote)
triggerNotePairs = (TriggerNoteToml -> (Text, NaviNote))
-> NonEmpty TriggerNoteToml -> NonEmpty (Text, NaviNote)
forall a b. (a -> b) -> NonEmpty a -> NonEmpty b
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
fmap TriggerNoteToml -> (Text, NaviNote)
toPair (CustomToml
toml CustomToml
-> Optic' A_Lens NoIx CustomToml (NonEmpty TriggerNoteToml)
-> NonEmpty TriggerNoteToml
forall k s (is :: IxList) a.
Is k A_Getter =>
s -> Optic' k is s a -> a
^. Optic' A_Lens NoIx CustomToml (NonEmpty TriggerNoteToml)
#triggerNotes)
    toPair :: TriggerNoteToml -> (Text, NaviNote)
toPair (MkTriggerNoteToml Text
t NaviNote
n) = (Text -> Text
T.strip Text
t, NaviNote
n)
    pi :: PollInterval
pi = PollInterval -> Maybe PollInterval -> PollInterval
forall a. a -> Maybe a -> a
fromMaybe (Natural -> PollInterval
MkPollInterval Natural
30) (CustomToml
toml CustomToml
-> Optic' A_Lens NoIx CustomToml (Maybe PollInterval)
-> Maybe PollInterval
forall k s (is :: IxList) a.
Is k A_Getter =>
s -> Optic' k is s a -> a
^. Optic' A_Lens NoIx CustomToml (Maybe PollInterval)
#pollInterval)

    toCommandResult :: Text -> CommandResult
toCommandResult = Maybe Text -> Maybe PollInterval -> Text -> CommandResult
MkCommandResult Maybe Text
forall a. Maybe a
Nothing Maybe PollInterval
forall a. Maybe a
Nothing
{-# INLINEABLE toEvent #-}

mkCustomEvent ::
  Maybe Text ->
  Command ->
  NonEmpty (Text, NaviNote) ->
  PollInterval ->
  RepeatEvent CommandResult ->
  ErrorNote ->
  Maybe CommandResultParserToml ->
  Event CommandResult CommandResult
mkCustomEvent :: Maybe Text
-> Command
-> NonEmpty (Text, NaviNote)
-> PollInterval
-> RepeatEvent CommandResult
-> ErrorNote
-> Maybe CommandResultParserToml
-> Event CommandResult CommandResult
mkCustomEvent Maybe Text
mname Command
cmd NonEmpty (Text, NaviNote)
noteList PollInterval
pollInterval RepeatEvent CommandResult
repeatEvent ErrorNote
errorNote Maybe CommandResultParserToml
mParser =
  MkEvent
    { Text
name :: Text
name :: Text
name,
      serviceType :: ServiceType CommandResult
serviceType = Command -> CommandResultParser -> ServiceType CommandResult
Custom Command
cmd CommandResultParser
parser,
      PollInterval
pollInterval :: PollInterval
pollInterval :: PollInterval
pollInterval,
      raiseAlert :: CommandResult -> Maybe (CommandResult, NaviNote)
raiseAlert = \CommandResult
r -> do
        NaviNote
note <- Text -> Map Text NaviNote -> Maybe NaviNote
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup (CommandResult
r CommandResult -> Optic' A_Lens NoIx CommandResult Text -> Text
forall k s (is :: IxList) a.
Is k A_Getter =>
s -> Optic' k is s a -> a
^. Optic' A_Lens NoIx CommandResult Text
#result) Map Text NaviNote
noteMap

        pure $ case CommandResult
r CommandResult
-> Optic' A_Lens NoIx CommandResult (Maybe Text) -> Maybe Text
forall k s (is :: IxList) a.
Is k A_Getter =>
s -> Optic' k is s a -> a
^. Optic' A_Lens NoIx CommandResult (Maybe Text)
#output of
          Maybe Text
Nothing -> (CommandResult
r, NaviNote
note)
          Just Text
output -> (CommandResult
r, Text -> NaviNote -> NaviNote
replaceOut Text
output NaviNote
note),
      RepeatEvent CommandResult
repeatEvent :: RepeatEvent CommandResult
repeatEvent :: RepeatEvent CommandResult
repeatEvent,
      ErrorNote
errorNote :: ErrorNote
errorNote :: ErrorNote
errorNote
    }
  where
    noteMap :: Map Text NaviNote
noteMap = [(Text, NaviNote)] -> Map Text NaviNote
forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList ([(Text, NaviNote)] -> Map Text NaviNote)
-> [(Text, NaviNote)] -> Map Text NaviNote
forall a b. (a -> b) -> a -> b
$ NonEmpty (Text, NaviNote) -> [(Text, NaviNote)]
forall a. NonEmpty a -> [a]
NE.toList NonEmpty (Text, NaviNote)
noteList
    name :: Text
name = Text -> Maybe Text -> Text
forall a. a -> Maybe a -> a
fromMaybe Text
"custom" Maybe Text
mname

    parser :: CommandResultParser
parser = case Maybe CommandResultParserToml
mParser of
      Just (MkCommandResultParserToml Text -> CommandResultParser
p) -> Text -> CommandResultParser
p Text
name
      Maybe CommandResultParserToml
Nothing -> CommandResultParser
defaultParser