-- | This module provides a service for alerts related to battery levels.
module Navi.Services.Battery.Percentage
  ( BatteryPercentageToml,
    toEvent,
  )
where

import Data.List.NonEmpty qualified as NE
import Data.Map (Map)
import Data.Map qualified as Map
import Navi.Data.NaviNote (NaviNote (..))
import Navi.Data.PollInterval (PollInterval (..))
import Navi.Event.Toml qualified as EventToml
import Navi.Event.Types (AnyEvent (..), ErrorNote, Event (..), RepeatEvent)
import Navi.Prelude
import Navi.Services.Battery.Percentage.Toml (BatteryPercentageNoteToml (..), BatteryPercentageToml)
import Navi.Services.Types (ServiceType (..))
import Numeric.Data.Interval qualified as Interval
import Pythia.Services.Battery
  ( Battery (..),
    BatteryApp,
    BatteryStatus (..),
    Percentage (..),
  )

-- | Transforms toml configuration data into an 'AnyEvent'.
toEvent :: (MonadIORef m) => BatteryPercentageToml -> m AnyEvent
toEvent :: forall (m :: OpticKind -> OpticKind).
MonadIORef m =>
BatteryPercentageToml -> m AnyEvent
toEvent BatteryPercentageToml
toml = do
  RepeatEvent Battery
repeatEvent <- forall (m :: OpticKind -> OpticKind) (a :: OpticKind).
MonadIORef m =>
Maybe RepeatEventToml -> m (RepeatEvent a)
EventToml.mRepeatEventTomlToVal forall (a :: OpticKind) b. (a -> b) -> a -> b
$ BatteryPercentageToml
toml forall (k :: OpticKind) (s :: OpticKind) (is :: IxList)
       (a :: OpticKind).
Is k A_Getter =>
s -> Optic' k is s a -> a
^. forall (a :: OpticKind). IsLabel "repeatEvent" a => a
#repeatEvent
  ErrorNote
errorNote <- forall (m :: OpticKind -> OpticKind).
MonadIORef m =>
Maybe ErrorNoteToml -> m ErrorNote
EventToml.mErrorNoteTomlToVal forall (a :: OpticKind) b. (a -> b) -> a -> b
$ BatteryPercentageToml
toml forall (k :: OpticKind) (s :: OpticKind) (is :: IxList)
       (a :: OpticKind).
Is k A_Getter =>
s -> Optic' k is s a -> a
^. forall (a :: OpticKind). IsLabel "errorNote" a => a
#errorNote
  let evt :: Event Battery
evt = NonEmpty (Percentage, NaviNote)
-> BatteryApp
-> PollInterval
-> RepeatEvent Battery
-> ErrorNote
-> Event Battery
mkBatteryEvent NonEmpty (Percentage, NaviNote)
percentNoteList BatteryApp
app PollInterval
pi RepeatEvent Battery
repeatEvent ErrorNote
errorNote
  forall (f :: OpticKind -> OpticKind) (a :: OpticKind).
Applicative f =>
a -> f a
pure forall (a :: OpticKind) b. (a -> b) -> a -> b
$ forall (result :: OpticKind).
(Eq result, Show result) =>
Event result -> AnyEvent
MkAnyEvent Event Battery
evt
  where
    percentNoteList :: NonEmpty (Percentage, NaviNote)
percentNoteList = BatteryPercentageNoteToml -> (Percentage, NaviNote)
tomlToNote forall (f :: OpticKind -> OpticKind) (a :: OpticKind)
       (b :: OpticKind).
Functor f =>
(a -> b) -> f a -> f b
<$> BatteryPercentageToml
toml forall (k :: OpticKind) (s :: OpticKind) (is :: IxList)
       (a :: OpticKind).
Is k A_Getter =>
s -> Optic' k is s a -> a
^. forall (a :: OpticKind). IsLabel "alerts" a => a
#alerts
    app :: BatteryApp
app = BatteryPercentageToml
toml forall (k :: OpticKind) (s :: OpticKind) (is :: IxList)
       (a :: OpticKind).
Is k A_Getter =>
s -> Optic' k is s a -> a
^. forall (a :: OpticKind). IsLabel "app" a => a
#app
    pi :: PollInterval
pi = forall (a :: OpticKind). a -> Maybe a -> a
fromMaybe (Natural -> PollInterval
MkPollInterval Natural
30) (BatteryPercentageToml
toml forall (k :: OpticKind) (s :: OpticKind) (is :: IxList)
       (a :: OpticKind).
Is k A_Getter =>
s -> Optic' k is s a -> a
^. forall (a :: OpticKind). IsLabel "pollInterval" a => a
#pollInterval)
{-# INLINEABLE toEvent #-}

tomlToNote :: BatteryPercentageNoteToml -> (Percentage, NaviNote)
tomlToNote :: BatteryPercentageNoteToml -> (Percentage, NaviNote)
tomlToNote BatteryPercentageNoteToml
toml =
  ( Percentage
percentage,
    Text
-> Maybe Text -> Maybe UrgencyLevel -> Maybe Timeout -> NaviNote
MkNaviNote
      Text
summary
      Maybe Text
body
      (BatteryPercentageNoteToml
toml forall (k :: OpticKind) (s :: OpticKind) (is :: IxList)
       (a :: OpticKind).
Is k A_Getter =>
s -> Optic' k is s a -> a
^. forall (a :: OpticKind). IsLabel "urgency" a => a
#urgency)
      (BatteryPercentageNoteToml
toml forall (k :: OpticKind) (s :: OpticKind) (is :: IxList)
       (a :: OpticKind).
Is k A_Getter =>
s -> Optic' k is s a -> a
^. forall (a :: OpticKind). IsLabel "mTimeout" a => a
#mTimeout)
  )
  where
    percentage :: Percentage
percentage = BatteryPercentageNoteToml
toml forall (k :: OpticKind) (s :: OpticKind) (is :: IxList)
       (a :: OpticKind).
Is k A_Getter =>
s -> Optic' k is s a -> a
^. forall (a :: OpticKind). IsLabel "percentage" a => a
#percentage
    summary :: Text
summary = Text
"Battery Percentage"
    body :: Maybe Text
body =
      forall (a :: OpticKind). a -> Maybe a
Just forall (a :: OpticKind) b. (a -> b) -> a -> b
$
        forall (a :: OpticKind). Show a => a -> Text
showt (forall (l :: Natural) (r :: Natural) (a :: OpticKind).
LRInterval l r a -> a
Interval.unLRInterval forall (a :: OpticKind) b. (a -> b) -> a -> b
$ Percentage
percentage forall (k :: OpticKind) (s :: OpticKind) (is :: IxList)
       (a :: OpticKind).
Is k A_Getter =>
s -> Optic' k is s a -> a
^. forall (a :: OpticKind). IsLabel "unPercentage" a => a
#unPercentage)
          forall (a :: OpticKind). Semigroup a => a -> a -> a
<> Text
"%"
{-# INLINEABLE tomlToNote #-}

mkBatteryEvent ::
  NonEmpty (Percentage, NaviNote) ->
  BatteryApp ->
  PollInterval ->
  RepeatEvent Battery ->
  ErrorNote ->
  Event Battery
mkBatteryEvent :: NonEmpty (Percentage, NaviNote)
-> BatteryApp
-> PollInterval
-> RepeatEvent Battery
-> ErrorNote
-> Event Battery
mkBatteryEvent NonEmpty (Percentage, NaviNote)
percentNoteList BatteryApp
batteryProgram PollInterval
pi RepeatEvent Battery
re ErrorNote
en =
  MkEvent
    { $sel:name:MkEvent :: Text
name = Text
"battery-percentage",
      $sel:serviceType:MkEvent :: ServiceType Battery
serviceType = BatteryApp -> ServiceType Battery
BatteryPercentage BatteryApp
batteryProgram,
      $sel:pollInterval:MkEvent :: PollInterval
pollInterval = PollInterval
pi,
      $sel:raiseAlert:MkEvent :: Battery -> Maybe NaviNote
raiseAlert = Map Percentage NaviNote -> Battery -> Maybe NaviNote
lookupPercent Map Percentage NaviNote
percentNoteMap,
      $sel:repeatEvent:MkEvent :: RepeatEvent Battery
repeatEvent = RepeatEvent Battery
re,
      $sel:errorNote:MkEvent :: ErrorNote
errorNote = ErrorNote
en
    }
  where
    percentNoteMap :: Map Percentage NaviNote
percentNoteMap = forall (k :: OpticKind) (a :: OpticKind).
Ord k =>
[(k, a)] -> Map k a
Map.fromList forall (a :: OpticKind) b. (a -> b) -> a -> b
$ forall (a :: OpticKind). NonEmpty a -> [a]
NE.toList NonEmpty (Percentage, NaviNote)
percentNoteList
{-# INLINEABLE mkBatteryEvent #-}

lookupPercent :: Map Percentage NaviNote -> Battery -> Maybe NaviNote
lookupPercent :: Map Percentage NaviNote -> Battery -> Maybe NaviNote
lookupPercent Map Percentage NaviNote
percentNoteMap Battery
state = case Battery
state forall (k :: OpticKind) (s :: OpticKind) (is :: IxList)
       (a :: OpticKind).
Is k A_Getter =>
s -> Optic' k is s a -> a
^. forall (a :: OpticKind). IsLabel "status" a => a
#status of
  BatteryStatus
Discharging -> forall (k :: OpticKind) (a :: OpticKind).
Ord k =>
k -> Map k a -> Maybe a
Map.lookup (Battery
state forall (k :: OpticKind) (s :: OpticKind) (is :: IxList)
       (a :: OpticKind).
Is k A_Getter =>
s -> Optic' k is s a -> a
^. forall (a :: OpticKind). IsLabel "percentage" a => a
#percentage) Map Percentage NaviNote
percentNoteMap
  BatteryStatus
_ -> forall (a :: OpticKind). Maybe a
Nothing
{-# INLINEABLE lookupPercent #-}