-- | This module provides a service for alerts related to battery statuses.
module Navi.Services.Battery.Status
  ( BatteryStatusToml,
    toEvent,
  )
where

import Navi.Data.NaviNote (NaviNote, Timeout)
import Navi.Data.NaviNote qualified as NNote
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.Battery.Status.Toml (BatteryStatusToml)
import Navi.Services.Types (ServiceType (BatteryStatus))
import Pythia.Services.Battery
  ( BatteryApp,
    BatteryStatus
      ( Charging,
        Discharging,
        Full,
        Pending
      ),
  )

-- | Transforms toml configuration data into an 'AnyEvent'.
toEvent ::
  (MonadIORef m) =>
  BatteryStatusToml ->
  m AnyEvent
toEvent :: forall (m :: Type -> Type).
MonadIORef m =>
BatteryStatusToml -> m AnyEvent
toEvent BatteryStatusToml
toml = do
  RepeatEvent BatteryStatus
repeatEvent <- Maybe RepeatEventToml -> m (RepeatEvent BatteryStatus)
forall (m :: Type -> Type) a.
MonadIORef m =>
Maybe RepeatEventToml -> m (RepeatEvent a)
EventToml.mRepeatEventTomlToVal (Maybe RepeatEventToml -> m (RepeatEvent BatteryStatus))
-> Maybe RepeatEventToml -> m (RepeatEvent BatteryStatus)
forall a b. (a -> b) -> a -> b
$ BatteryStatusToml
toml BatteryStatusToml
-> Optic' A_Lens NoIx BatteryStatusToml (Maybe RepeatEventToml)
-> Maybe RepeatEventToml
forall k s (is :: IxList) a.
Is k A_Getter =>
s -> Optic' k is s a -> a
^. Optic' A_Lens NoIx BatteryStatusToml (Maybe RepeatEventToml)
#repeatEvent
  ErrorNote
errorNote <- Maybe ErrorNoteToml -> m ErrorNote
forall (m :: Type -> Type).
MonadIORef m =>
Maybe ErrorNoteToml -> m ErrorNote
EventToml.mErrorNoteTomlToVal (Maybe ErrorNoteToml -> m ErrorNote)
-> Maybe ErrorNoteToml -> m ErrorNote
forall a b. (a -> b) -> a -> b
$ BatteryStatusToml
toml BatteryStatusToml
-> Optic' A_Lens NoIx BatteryStatusToml (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 BatteryStatusToml (Maybe ErrorNoteToml)
#errorNote
  let evt :: Event BatteryStatus BatteryStatus
evt = Maybe Timeout
-> BatteryApp
-> PollInterval
-> RepeatEvent BatteryStatus
-> ErrorNote
-> Event BatteryStatus BatteryStatus
mkStatusEvent Maybe Timeout
to BatteryApp
cfg PollInterval
pi RepeatEvent BatteryStatus
repeatEvent ErrorNote
errorNote
  AnyEvent -> m AnyEvent
forall a. a -> m a
forall (f :: Type -> Type) a. Applicative f => a -> f a
pure (AnyEvent -> m AnyEvent) -> AnyEvent -> m AnyEvent
forall a b. (a -> b) -> a -> b
$ Event BatteryStatus BatteryStatus -> AnyEvent
forall trigger result.
(Ord trigger, Show result, Show trigger) =>
Event result trigger -> AnyEvent
MkAnyEvent Event BatteryStatus BatteryStatus
evt
  where
    cfg :: BatteryApp
cfg = BatteryStatusToml
toml BatteryStatusToml
-> Optic' A_Lens NoIx BatteryStatusToml BatteryApp -> BatteryApp
forall k s (is :: IxList) a.
Is k A_Getter =>
s -> Optic' k is s a -> a
^. Optic' A_Lens NoIx BatteryStatusToml BatteryApp
#app
    to :: Maybe Timeout
to = BatteryStatusToml
toml BatteryStatusToml
-> Optic' A_Lens NoIx BatteryStatusToml (Maybe Timeout)
-> Maybe Timeout
forall k s (is :: IxList) a.
Is k A_Getter =>
s -> Optic' k is s a -> a
^. Optic' A_Lens NoIx BatteryStatusToml (Maybe Timeout)
#mTimeout
    pi :: PollInterval
pi = PollInterval -> Maybe PollInterval -> PollInterval
forall a. a -> Maybe a -> a
fromMaybe (Natural -> PollInterval
MkPollInterval Natural
30) (BatteryStatusToml
toml BatteryStatusToml
-> Optic' A_Lens NoIx BatteryStatusToml (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 BatteryStatusToml (Maybe PollInterval)
#pollInterval)
{-# INLINEABLE toEvent #-}

mkStatusEvent ::
  Maybe Timeout ->
  BatteryApp ->
  PollInterval ->
  RepeatEvent BatteryStatus ->
  ErrorNote ->
  Event BatteryStatus BatteryStatus
mkStatusEvent :: Maybe Timeout
-> BatteryApp
-> PollInterval
-> RepeatEvent BatteryStatus
-> ErrorNote
-> Event BatteryStatus BatteryStatus
mkStatusEvent Maybe Timeout
to BatteryApp
cfg PollInterval
pi RepeatEvent BatteryStatus
repeatEvent ErrorNote
errorNote =
  MkEvent
    { name :: Text
name = Text
"battery-status",
      serviceType :: ServiceType BatteryStatus
serviceType = BatteryApp -> ServiceType BatteryStatus
BatteryStatus BatteryApp
cfg,
      pollInterval :: PollInterval
pollInterval = PollInterval
pi,
      raiseAlert :: BatteryStatus -> Maybe (BatteryStatus, NaviNote)
raiseAlert = Maybe Timeout -> BatteryStatus -> Maybe (BatteryStatus, NaviNote)
toNote Maybe Timeout
to,
      repeatEvent :: RepeatEvent BatteryStatus
repeatEvent = RepeatEvent BatteryStatus
repeatEvent,
      errorNote :: ErrorNote
errorNote = ErrorNote
errorNote
    }

toNote :: Maybe Timeout -> BatteryStatus -> Maybe (BatteryStatus, NaviNote)
toNote :: Maybe Timeout -> BatteryStatus -> Maybe (BatteryStatus, NaviNote)
toNote Maybe Timeout
timeout BatteryStatus
status = (BatteryStatus
status,) (NaviNote -> (BatteryStatus, NaviNote))
-> Maybe NaviNote -> Maybe (BatteryStatus, NaviNote)
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe Timeout -> Text -> Maybe NaviNote
toNote' Maybe Timeout
timeout (BatteryStatus -> Text
forall {a}. IsString a => BatteryStatus -> a
fromStatus BatteryStatus
status)
  where
    fromStatus :: BatteryStatus -> a
fromStatus BatteryStatus
Charging = a
"Battery charging"
    fromStatus BatteryStatus
Discharging = a
"Battery discharging"
    fromStatus BatteryStatus
Full = a
"Battery full"
    fromStatus BatteryStatus
Pending = a
"Battery pending"

toNote' :: Maybe Timeout -> Text -> Maybe NaviNote
toNote' :: Maybe Timeout -> Text -> Maybe NaviNote
toNote' Maybe Timeout
timeout Text
msg =
  NaviNote -> Maybe NaviNote
forall a. a -> Maybe a
Just
    (NaviNote -> Maybe NaviNote) -> NaviNote -> Maybe NaviNote
forall a b. (a -> b) -> a -> b
$ NNote.MkNaviNote
      { summary :: Text
NNote.summary = Text
"Battery Status",
        body :: Maybe Text
NNote.body = Text -> Maybe Text
forall a. a -> Maybe a
Just Text
msg,
        urgency :: Maybe UrgencyLevel
NNote.urgency = Maybe UrgencyLevel
forall a. Maybe a
Nothing,
        timeout :: Maybe Timeout
NNote.timeout = Maybe Timeout
timeout
      }