{-# LANGUAGE UndecidableInstances #-}

-- | Provides environment for usage with NotifySend.
module Navi.Env.NotifySend
  ( mkNotifySendEnv,
    naviToNotifySend,
  )
where

import DBus.Notify (UrgencyLevel (Critical, Low, Normal))
import Navi.Config.Types (Config, NoteSystem (NotifySend))
import Navi.Data.NaviLog (LogEnv)
import Navi.Data.NaviNote (NaviNote, Timeout (Never, Seconds))
import Navi.Env.Core (Env (MkEnv, events, logEnv, noteQueue, notifySystem))
import Navi.Prelude
import Navi.Utils qualified as Utils

-- | Creates a 'NotifySendEnv' from the provided log types and configuration
-- data.
mkNotifySendEnv ::
  (MonadSTM m) =>
  Maybe LogEnv ->
  Config ->
  m Env
mkNotifySendEnv :: forall (m :: Type -> Type).
MonadSTM m =>
Maybe LogEnv -> Config -> m Env
mkNotifySendEnv Maybe LogEnv
logEnv Config
config = do
  TBQueue NaviNote
noteQueue <- Natural -> m (TBQueue NaviNote)
forall (m :: Type -> Type) a.
(HasCallStack, MonadSTM m) =>
Natural -> m (TBQueue a)
newTBQueueA Natural
1000
  pure
    $ MkEnv
      { events :: NonEmpty AnyEvent
events = Config
config Config
-> Optic' A_Lens NoIx Config (NonEmpty AnyEvent)
-> NonEmpty AnyEvent
forall k s (is :: IxList) a.
Is k A_Getter =>
s -> Optic' k is s a -> a
^. Optic' A_Lens NoIx Config (NonEmpty AnyEvent)
#events,
        Maybe LogEnv
logEnv :: Maybe LogEnv
logEnv :: Maybe LogEnv
logEnv,
        TBQueue NaviNote
noteQueue :: TBQueue NaviNote
noteQueue :: TBQueue NaviNote
noteQueue,
        notifySystem :: NoteSystem 'ConfigPhaseEnv
notifySystem = NoteSystem 'ConfigPhaseEnv
forall (p :: ConfigPhase). NoteSystem p
NotifySend
      }
{-# INLINEABLE mkNotifySendEnv #-}

-- | Turns a 'NaviNote' into a string to be sent with the notify-send tool.
naviToNotifySend :: NaviNote -> Text
naviToNotifySend :: NaviNote -> Text
naviToNotifySend NaviNote
naviNote = Text
txt
  where
    txt :: Text
txt =
      [Text] -> Text
forall a. Monoid a => [a] -> a
mconcat
        [ Text
"notify-send \"",
          Text
summary,
          Text
"\" ",
          Text
body,
          Text -> (UrgencyLevel -> Text) -> Maybe UrgencyLevel -> Text
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Text
"" UrgencyLevel -> Text
forall {a}. IsString a => UrgencyLevel -> a
ulToNS (NaviNote
naviNote NaviNote
-> Optic' A_Lens NoIx NaviNote (Maybe UrgencyLevel)
-> Maybe UrgencyLevel
forall k s (is :: IxList) a.
Is k A_Getter =>
s -> Optic' k is s a -> a
^. Optic' A_Lens NoIx NaviNote (Maybe UrgencyLevel)
#urgency),
          Text -> (Timeout -> Text) -> Maybe Timeout -> Text
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Text
"" Timeout -> Text
timeoutToNS (NaviNote
naviNote NaviNote
-> Optic' A_Lens NoIx NaviNote (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 NaviNote (Maybe Timeout)
#timeout)
        ]

    summary :: Text
summary = Text -> Text
Utils.escapeDoubleQuotes (Text -> Text) -> Text -> Text
forall a b. (a -> b) -> a -> b
$ NaviNote
naviNote NaviNote -> Optic' A_Lens NoIx NaviNote Text -> Text
forall k s (is :: IxList) a.
Is k A_Getter =>
s -> Optic' k is s a -> a
^. Optic' A_Lens NoIx NaviNote Text
#summary
    body :: Text
body =
      Text -> (Text -> Text) -> Maybe Text -> Text
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Text
"" ((\Text
b -> Text
" \"" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
b Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"\" ") (Text -> Text) -> (Text -> Text) -> Text -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> Type) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Text -> Text
Utils.escapeDoubleQuotes)
        (Maybe Text -> Text) -> Maybe Text -> Text
forall a b. (a -> b) -> a -> b
$ NaviNote
naviNote
        NaviNote -> Optic' A_Lens NoIx NaviNote (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 NaviNote (Maybe Text)
#body

    ulToNS :: UrgencyLevel -> a
ulToNS UrgencyLevel
Low = a
" --urgency low "
    ulToNS UrgencyLevel
Normal = a
" --urgency normal "
    ulToNS UrgencyLevel
Critical = a
" --urgency critical "

    timeoutToNS :: Timeout -> Text
timeoutToNS Timeout
Never = Text
""
    timeoutToNS (Seconds Word16
s) =
      String -> Text
packText
        (String -> Text) -> String -> Text
forall a b. (a -> b) -> a -> b
$ String
" --expire-time "
        String -> String -> String
forall a. Semigroup a => a -> a -> a
<> Word16 -> String
forall a. Show a => a -> String
show (Word16
s Word16 -> Word16 -> Word16
forall a. Num a => a -> a -> a
* Word16
1_000)
        String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
" "