content: {-# LANGUAGE NamedFieldPuns #-}
  {-# LANGUAGE OverloadedStrings #-}
  {-# LANGUAGE ScopedTypeVariables #-}
  
  module Cardano.Tracer.Handlers.RTView.UI.Notifications
    ( getCurrentEmailSettings
    , getCurrentEventsSettings
    , restoreEmailSettings
    , restoreEventsSettings
    , saveEmailSettings
    , saveEventsSettings
    , setNotifyIconState
    , setStatusTestEmailButton
    ) where
  
  import           Cardano.Tracer.Environment
  import           Cardano.Tracer.Handlers.Notifications.Settings
  import           Cardano.Tracer.Handlers.Notifications.Timer
  import           Cardano.Tracer.Handlers.Notifications.Types
  import           Cardano.Tracer.Handlers.RTView.UI.Img.Icons
  import           Cardano.Tracer.Handlers.RTView.UI.JS.Utils
  import           Cardano.Tracer.Handlers.RTView.UI.Utils
  import           Cardano.Tracer.Handlers.Utils
  
  import           Control.Monad (unless, when)
  import           Data.Maybe (fromMaybe)
  import           Data.Text (pack, unpack)
  import qualified Data.Text as T
  import           Data.Text.Read (decimal)
  
  import qualified Graphics.UI.Threepenny as UI
  import           Graphics.UI.Threepenny.Core
  
  restoreEmailSettings :: TracerEnv -> UI ()
  restoreEmailSettings TracerEnv{teStateDir} = do
    eSettings <- liftIO $ readSavedEmailSettings teStateDir
    setEmailSettings eSettings
    setStatusTestEmailButton
   where
    setEmailSettings settings = do
      window <- askWindow
      setValue window (unpack $ esSMTPHost settings)  "es-smtp-host"
      setValue window (show   $ esSMTPPort settings)  "es-smtp-port"
      setValue window (unpack $ esUsername settings)  "es-username"
      setValue window (unpack $ esPassword settings)  "es-password"
      setValue window (show   $ esSSL settings)       "es-ssl"
      setValue window (unpack $ esEmailFrom settings) "es-email-from"
      setValue window (unpack $ esEmailTo settings)   "es-email-to"
      setValue window (unpack $ esSubject settings)   "es-subject"
  
    setValue window elValue elId =
      unless (null elValue || elValue == "-1") $
        findAndSet (set value elValue) window elId
  
  restoreEventsSettings :: TracerEnv -> UI ()
  restoreEventsSettings TracerEnv{teStateDir} = do
    eSettings <- liftIO $ readSavedEventsSettings teStateDir
    setEventsSettings eSettings
    setNotifyIconState
    setSwitchAllState eSettings
   where
    setEventsSettings settings = do
      setState (fst $ evsWarnings settings)         "switch-warnings"
      setState (fst $ evsErrors settings)           "switch-errors"
      setState (fst $ evsCriticals settings)        "switch-criticals"
      setState (fst $ evsAlerts settings)           "switch-alerts"
      setState (fst $ evsEmergencies settings)      "switch-emergencies"
      setState (fst $ evsNodeDisconnected settings) "switch-node-disconnected"
  
      setPeriod (snd $ evsWarnings settings)         "select-period-warnings"
      setPeriod (snd $ evsErrors settings)           "select-period-errors"
      setPeriod (snd $ evsCriticals settings)        "select-period-criticals"
      setPeriod (snd $ evsAlerts settings)           "select-period-alerts"
      setPeriod (snd $ evsEmergencies settings)      "select-period-emergencies"
      setPeriod (snd $ evsNodeDisconnected settings) "select-period-node-disconnected"
  
    setState elState elId = do
      window <- askWindow
      findAndSet (set UI.checked elState) window elId
  
    setPeriod elPeriod elId =
      selectOption elId $ fromIntegral elPeriod
  
    setSwitchAllState settings = do
      let allChecked = and
            [ fst (evsWarnings settings)
            , fst (evsErrors settings)
            , fst (evsCriticals settings)
            , fst (evsAlerts settings)
            , fst (evsEmergencies settings)
            , fst (evsNodeDisconnected settings)
            ]
      setState allChecked "switch-all"
  
  setNotifyIconState :: UI ()
  setNotifyIconState = do
    window <- askWindow
    settings <- getCurrentEventsSettings
    let switches =
          [ fst (evsWarnings settings)
          , fst (evsErrors settings)
          , fst (evsCriticals settings)
          , fst (evsAlerts settings)
          , fst (evsEmergencies settings)
          ]
        anyChecked = or switches
        noChecked  = not anyChecked
        allChecked = and switches
    when anyChecked $ findAndSet (set html rtViewNotifySVG)   window "notifications-icon"
    when noChecked  $ findAndSet (set html rtViewNoNotifySVG) window "notifications-icon"
    findAndSet (set UI.checked allChecked) window "switch-all"
  
  saveEmailSettings :: TracerEnv -> UI ()
  saveEmailSettings tracerEnv =
    (liftIO . saveEmailSettingsOnDisk tracerEnv) =<< getCurrentEmailSettings
  
  saveEventsSettings :: TracerEnv -> UI ()
  saveEventsSettings tracerEnv =
    (liftIO . saveEventsSettingsOnDisk tracerEnv) =<< getCurrentEventsSettings
  
  getCurrentEmailSettings :: UI EmailSettings
  getCurrentEmailSettings = do
    window <- askWindow
    smtpHost  <- findAndGetValue window "es-smtp-host"
    smtpPort  <- findAndGetValue window "es-smtp-port"
    username  <- findAndGetValue window "es-username"
    password  <- findAndGetValue window "es-password"
    ssl       <- findAndGetValue window "es-ssl"
    emailFrom <- findAndGetValue window "es-email-from"
    emailTo   <- findAndGetValue window "es-email-to"
    subject   <- findAndGetValue window "es-subject"
    return $ EmailSettings
      { esSMTPHost  = pack smtpHost
      , esSMTPPort  = readInt (pack smtpPort) (-1)
      , esUsername  = pack username
      , esPassword  = pack password
      , esSSL       = read ssl
      , esEmailFrom = pack emailFrom
      , esEmailTo   = pack emailTo
      , esSubject   = pack subject
      }
  
  getCurrentEventsSettings :: UI EventsSettings
  getCurrentEventsSettings = do
    window <- askWindow
  
    warningsState    <- fromMaybe False <$> findAndGetCheckboxState window "switch-warnings"
    errorsState      <- fromMaybe False <$> findAndGetCheckboxState window "switch-errors"
    criticalsState   <- fromMaybe False <$> findAndGetCheckboxState window "switch-criticals"
    alertsState      <- fromMaybe False <$> findAndGetCheckboxState window "switch-alerts"
    emergenciesState <- fromMaybe False <$> findAndGetCheckboxState window "switch-emergencies"
    nodeDisconState  <- fromMaybe False <$> findAndGetCheckboxState window "switch-node-disconnected"
  
    warningsPeriod    <- readPeriod 1800 <$> findAndGetValue window "select-period-warnings"
    errorsPeriod      <- readPeriod 1800 <$> findAndGetValue window "select-period-errors"
    criticalsPeriod   <- readPeriod 1800 <$> findAndGetValue window "select-period-criticals"
    alertsPeriod      <- readPeriod 1800 <$> findAndGetValue window "select-period-alerts"
    emergenciesPeriod <- readPeriod 1800 <$> findAndGetValue window "select-period-emergencies"
    nodeDisconPeriod  <- readPeriod 1800 <$> findAndGetValue window "select-period-node-disconnected"
  
    return $ EventsSettings
      { evsWarnings         = (warningsState,    warningsPeriod)
      , evsErrors           = (errorsState,      errorsPeriod)
      , evsCriticals        = (criticalsState,   criticalsPeriod)
      , evsAlerts           = (alertsState,      alertsPeriod)
      , evsEmergencies      = (emergenciesState, emergenciesPeriod)
      , evsNodeDisconnected = (nodeDisconState,  nodeDisconPeriod)
      }
   where
    readPeriod :: PeriodInSec -> String -> PeriodInSec
    readPeriod defP s =
      case decimal (pack s) of
        Left _ -> defP
        Right (i :: Int, _) -> fromIntegral i
  
  setStatusTestEmailButton :: UI ()
  setStatusTestEmailButton = do
    EmailSettings host _ user pass _ eFrom eTo _ <- getCurrentEmailSettings
    let allRequiredIsHere =
             isHere host
          && isHere user
          && isHere pass
          && isHere eFrom
          && isHere eTo
    window <- askWindow
    findAndSet (set UI.enabled allRequiredIsHere) window "send-test-email"
   where
    isHere = not . T.null
  