{-# LANGUAGE UndecidableInstances #-}

module Shrun.Configuration.Data.CommandLogging
  ( -- * Types
    ReportReadErrorsSwitch (..),
    CommandLoggingP (..),
    CommandLoggingArgs,
    CommandLoggingToml,
    CommandLoggingMerged,
    CommandLoggingEnv,

    -- * Functions
    mergeCommandLogging,
    toEnv,

    -- * Misc
    defaultMerged,
  )
where

import Shrun.Configuration.Data.CommandLogging.PollInterval (PollInterval)
import Shrun.Configuration.Data.CommandLogging.ReadSize (ReadSize)
import Shrun.Configuration.Data.ConfigPhase
  ( ConfigPhase
      ( ConfigPhaseArgs,
        ConfigPhaseEnv,
        ConfigPhaseMerged,
        ConfigPhaseToml
      ),
    ConfigPhaseF,
    SwitchF,
  )
import Shrun.Configuration.Data.WithDisabled (WithDisabled, (<>?), (<>?.))
import Shrun.Configuration.Data.WithDisabled qualified as WD
import Shrun.Configuration.Default (Default (def))
import Shrun.Prelude

-- | Switch for logging read errors
data ReportReadErrorsSwitch
  = ReportReadErrorsOff
  | ReportReadErrorsOn
  deriving stock (ReportReadErrorsSwitch -> ReportReadErrorsSwitch -> Bool
(ReportReadErrorsSwitch -> ReportReadErrorsSwitch -> Bool)
-> (ReportReadErrorsSwitch -> ReportReadErrorsSwitch -> Bool)
-> Eq ReportReadErrorsSwitch
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: ReportReadErrorsSwitch -> ReportReadErrorsSwitch -> Bool
== :: ReportReadErrorsSwitch -> ReportReadErrorsSwitch -> Bool
$c/= :: ReportReadErrorsSwitch -> ReportReadErrorsSwitch -> Bool
/= :: ReportReadErrorsSwitch -> ReportReadErrorsSwitch -> Bool
Eq, Int -> ReportReadErrorsSwitch -> ShowS
[ReportReadErrorsSwitch] -> ShowS
ReportReadErrorsSwitch -> String
(Int -> ReportReadErrorsSwitch -> ShowS)
-> (ReportReadErrorsSwitch -> String)
-> ([ReportReadErrorsSwitch] -> ShowS)
-> Show ReportReadErrorsSwitch
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> ReportReadErrorsSwitch -> ShowS
showsPrec :: Int -> ReportReadErrorsSwitch -> ShowS
$cshow :: ReportReadErrorsSwitch -> String
show :: ReportReadErrorsSwitch -> String
$cshowList :: [ReportReadErrorsSwitch] -> ShowS
showList :: [ReportReadErrorsSwitch] -> ShowS
Show)

instance Default ReportReadErrorsSwitch where
  def :: ReportReadErrorsSwitch
def = ReportReadErrorsSwitch
ReportReadErrorsOff

instance
  ( k ~ An_Iso,
    a ~ Bool,
    b ~ Bool
  ) =>
  LabelOptic
    "boolIso"
    k
    ReportReadErrorsSwitch
    ReportReadErrorsSwitch
    a
    b
  where
  labelOptic :: Optic k NoIx ReportReadErrorsSwitch ReportReadErrorsSwitch a b
labelOptic =
    (ReportReadErrorsSwitch -> a)
-> (b -> ReportReadErrorsSwitch)
-> Iso ReportReadErrorsSwitch ReportReadErrorsSwitch a b
forall s a b t. (s -> a) -> (b -> t) -> Iso s t a b
iso
      (\cases ReportReadErrorsSwitch
ReportReadErrorsOn -> a
Bool
True; ReportReadErrorsSwitch
ReportReadErrorsOff -> a
Bool
False)
      (\cases b
Bool
True -> ReportReadErrorsSwitch
ReportReadErrorsOn; b
Bool
False -> ReportReadErrorsSwitch
ReportReadErrorsOff)
  {-# INLINE labelOptic #-}

-- | Holds config related to (console and file) command logging.
type CommandLoggingP :: ConfigPhase -> Type
data CommandLoggingP p = MkCommandLoggingP
  { -- | How often to poll commands for logs, in microseconds.
    forall (p :: ConfigPhase).
CommandLoggingP p -> ConfigPhaseF p PollInterval
pollInterval :: ConfigPhaseF p PollInterval,
    -- | Determines the max log size we read from commands in one go.
    -- Note this is not on commandLogging or fileLogging since it affects both.
    forall (p :: ConfigPhase).
CommandLoggingP p -> ConfigPhaseF p ReadSize
readSize :: ConfigPhaseF p ReadSize,
    -- | Determines if we should log read errors.
    forall (p :: ConfigPhase).
CommandLoggingP p -> SwitchF p ReportReadErrorsSwitch
reportReadErrors :: SwitchF p ReportReadErrorsSwitch
  }

instance
  (k ~ A_Lens, a ~ ConfigPhaseF p PollInterval, b ~ ConfigPhaseF p PollInterval) =>
  LabelOptic "pollInterval" k (CommandLoggingP p) (CommandLoggingP p) a b
  where
  labelOptic :: Optic k NoIx (CommandLoggingP p) (CommandLoggingP p) a b
labelOptic =
    LensVL (CommandLoggingP p) (CommandLoggingP p) a b
-> Lens (CommandLoggingP p) (CommandLoggingP p) a b
forall s t a b. LensVL s t a b -> Lens s t a b
lensVL
      (LensVL (CommandLoggingP p) (CommandLoggingP p) a b
 -> Lens (CommandLoggingP p) (CommandLoggingP p) a b)
-> LensVL (CommandLoggingP p) (CommandLoggingP p) a b
-> Lens (CommandLoggingP p) (CommandLoggingP p) a b
forall a b. (a -> b) -> a -> b
$ \a -> f b
f
         ( MkCommandLoggingP
             ConfigPhaseF p PollInterval
_pollInterval
             ConfigPhaseF p ReadSize
_readSize
             SwitchF p ReportReadErrorsSwitch
_reportReadErrors
           ) ->
          (b -> CommandLoggingP p) -> f b -> f (CommandLoggingP p)
forall a b. (a -> b) -> f a -> f b
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
fmap
            ( \b
pollInterval' ->
                ConfigPhaseF p PollInterval
-> ConfigPhaseF p ReadSize
-> SwitchF p ReportReadErrorsSwitch
-> CommandLoggingP p
forall (p :: ConfigPhase).
ConfigPhaseF p PollInterval
-> ConfigPhaseF p ReadSize
-> SwitchF p ReportReadErrorsSwitch
-> CommandLoggingP p
MkCommandLoggingP
                  b
ConfigPhaseF p PollInterval
pollInterval'
                  ConfigPhaseF p ReadSize
_readSize
                  SwitchF p ReportReadErrorsSwitch
_reportReadErrors
            )
            (a -> f b
f a
ConfigPhaseF p PollInterval
_pollInterval)
  {-# INLINE labelOptic #-}

instance
  (k ~ A_Lens, a ~ ConfigPhaseF p ReadSize, b ~ ConfigPhaseF p ReadSize) =>
  LabelOptic "readSize" k (CommandLoggingP p) (CommandLoggingP p) a b
  where
  labelOptic :: Optic k NoIx (CommandLoggingP p) (CommandLoggingP p) a b
labelOptic =
    LensVL (CommandLoggingP p) (CommandLoggingP p) a b
-> Lens (CommandLoggingP p) (CommandLoggingP p) a b
forall s t a b. LensVL s t a b -> Lens s t a b
lensVL
      (LensVL (CommandLoggingP p) (CommandLoggingP p) a b
 -> Lens (CommandLoggingP p) (CommandLoggingP p) a b)
-> LensVL (CommandLoggingP p) (CommandLoggingP p) a b
-> Lens (CommandLoggingP p) (CommandLoggingP p) a b
forall a b. (a -> b) -> a -> b
$ \a -> f b
f
         ( MkCommandLoggingP
             ConfigPhaseF p PollInterval
_pollInterval
             ConfigPhaseF p ReadSize
_readSize
             SwitchF p ReportReadErrorsSwitch
_reportReadErrors
           ) ->
          (b -> CommandLoggingP p) -> f b -> f (CommandLoggingP p)
forall a b. (a -> b) -> f a -> f b
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
fmap
            ( \b
readSize' ->
                ConfigPhaseF p PollInterval
-> ConfigPhaseF p ReadSize
-> SwitchF p ReportReadErrorsSwitch
-> CommandLoggingP p
forall (p :: ConfigPhase).
ConfigPhaseF p PollInterval
-> ConfigPhaseF p ReadSize
-> SwitchF p ReportReadErrorsSwitch
-> CommandLoggingP p
MkCommandLoggingP
                  ConfigPhaseF p PollInterval
_pollInterval
                  b
ConfigPhaseF p ReadSize
readSize'
                  SwitchF p ReportReadErrorsSwitch
_reportReadErrors
            )
            (a -> f b
f a
ConfigPhaseF p ReadSize
_readSize)
  {-# INLINE labelOptic #-}

instance
  (k ~ A_Lens, a ~ SwitchF p ReportReadErrorsSwitch, b ~ SwitchF p ReportReadErrorsSwitch) =>
  LabelOptic "reportReadErrors" k (CommandLoggingP p) (CommandLoggingP p) a b
  where
  labelOptic :: Optic k NoIx (CommandLoggingP p) (CommandLoggingP p) a b
labelOptic =
    LensVL (CommandLoggingP p) (CommandLoggingP p) a b
-> Lens (CommandLoggingP p) (CommandLoggingP p) a b
forall s t a b. LensVL s t a b -> Lens s t a b
lensVL
      (LensVL (CommandLoggingP p) (CommandLoggingP p) a b
 -> Lens (CommandLoggingP p) (CommandLoggingP p) a b)
-> LensVL (CommandLoggingP p) (CommandLoggingP p) a b
-> Lens (CommandLoggingP p) (CommandLoggingP p) a b
forall a b. (a -> b) -> a -> b
$ \a -> f b
f
         ( MkCommandLoggingP
             ConfigPhaseF p PollInterval
_pollInterval
             ConfigPhaseF p ReadSize
_readSize
             SwitchF p ReportReadErrorsSwitch
_reportReadErrors
           ) ->
          (b -> CommandLoggingP p) -> f b -> f (CommandLoggingP p)
forall a b. (a -> b) -> f a -> f b
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
fmap
            ( ConfigPhaseF p PollInterval
-> ConfigPhaseF p ReadSize
-> SwitchF p ReportReadErrorsSwitch
-> CommandLoggingP p
forall (p :: ConfigPhase).
ConfigPhaseF p PollInterval
-> ConfigPhaseF p ReadSize
-> SwitchF p ReportReadErrorsSwitch
-> CommandLoggingP p
MkCommandLoggingP
                ConfigPhaseF p PollInterval
_pollInterval
                ConfigPhaseF p ReadSize
_readSize
            )
            (a -> f b
f a
SwitchF p ReportReadErrorsSwitch
_reportReadErrors)
  {-# INLINE labelOptic #-}

type CommandLoggingArgs = CommandLoggingP ConfigPhaseArgs

type CommandLoggingToml = CommandLoggingP ConfigPhaseToml

type CommandLoggingMerged = CommandLoggingP ConfigPhaseMerged

type CommandLoggingEnv = CommandLoggingP ConfigPhaseEnv

deriving stock instance Eq (CommandLoggingP ConfigPhaseArgs)

deriving stock instance Show (CommandLoggingP ConfigPhaseArgs)

deriving stock instance Eq (CommandLoggingP ConfigPhaseToml)

deriving stock instance Show (CommandLoggingP ConfigPhaseToml)

deriving stock instance Eq (CommandLoggingP ConfigPhaseMerged)

deriving stock instance Show (CommandLoggingP ConfigPhaseMerged)

instance
  ( Default (ConfigPhaseF p PollInterval),
    Default (ConfigPhaseF p ReadSize),
    Default (SwitchF p ReportReadErrorsSwitch)
  ) =>
  Default (CommandLoggingP p)
  where
  def :: CommandLoggingP p
def =
    MkCommandLoggingP
      { pollInterval :: ConfigPhaseF p PollInterval
pollInterval = ConfigPhaseF p PollInterval
forall a. Default a => a
def,
        readSize :: ConfigPhaseF p ReadSize
readSize = ConfigPhaseF p ReadSize
forall a. Default a => a
def,
        reportReadErrors :: SwitchF p ReportReadErrorsSwitch
reportReadErrors = SwitchF p ReportReadErrorsSwitch
forall a. Default a => a
def
      }

-- | Merges args and toml configs.
mergeCommandLogging ::
  CommandLoggingArgs ->
  Maybe CommandLoggingToml ->
  CommandLoggingMerged
mergeCommandLogging :: CommandLoggingArgs
-> Maybe CommandLoggingToml -> CommandLoggingMerged
mergeCommandLogging CommandLoggingArgs
args Maybe CommandLoggingToml
mToml =
  MkCommandLoggingP
    { pollInterval :: ConfigPhaseF 'ConfigPhaseMerged PollInterval
pollInterval =
        (CommandLoggingArgs
args CommandLoggingArgs
-> Optic'
     A_Lens NoIx CommandLoggingArgs (WithDisabled PollInterval)
-> WithDisabled PollInterval
forall k s (is :: IxList) a.
Is k A_Getter =>
s -> Optic' k is s a -> a
^. Optic' A_Lens NoIx CommandLoggingArgs (WithDisabled PollInterval)
#pollInterval) WithDisabled PollInterval -> Maybe PollInterval -> PollInterval
forall a. Default a => WithDisabled a -> Maybe a -> a
<>?. (CommandLoggingToml
toml CommandLoggingToml
-> Optic' A_Lens NoIx CommandLoggingToml (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 CommandLoggingToml (Maybe PollInterval)
#pollInterval),
      readSize :: ConfigPhaseF 'ConfigPhaseMerged ReadSize
readSize =
        (CommandLoggingArgs
args CommandLoggingArgs
-> Optic' A_Lens NoIx CommandLoggingArgs (WithDisabled ReadSize)
-> WithDisabled ReadSize
forall k s (is :: IxList) a.
Is k A_Getter =>
s -> Optic' k is s a -> a
^. Optic' A_Lens NoIx CommandLoggingArgs (WithDisabled ReadSize)
#readSize) WithDisabled ReadSize -> Maybe ReadSize -> ReadSize
forall a. Default a => WithDisabled a -> Maybe a -> a
<>?. (CommandLoggingToml
toml CommandLoggingToml
-> Optic' A_Lens NoIx CommandLoggingToml (Maybe ReadSize)
-> Maybe ReadSize
forall k s (is :: IxList) a.
Is k A_Getter =>
s -> Optic' k is s a -> a
^. Optic' A_Lens NoIx CommandLoggingToml (Maybe ReadSize)
#readSize),
      reportReadErrors :: SwitchF 'ConfigPhaseMerged ReportReadErrorsSwitch
reportReadErrors =
        WithDisabled ReportReadErrorsSwitch -> ReportReadErrorsSwitch
forall a. Default a => WithDisabled a -> a
WD.fromDefault
          ( Optic' An_Iso NoIx ReportReadErrorsSwitch Bool
-> Bool -> ReportReadErrorsSwitch
forall k (is :: IxList) t b.
Is k A_Review =>
Optic' k is t b -> b -> t
review Optic' An_Iso NoIx ReportReadErrorsSwitch Bool
#boolIso
              (Bool -> ReportReadErrorsSwitch)
-> WithDisabled Bool -> WithDisabled ReportReadErrorsSwitch
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
<$> WithDisabled Bool
argsReportReadErrors
              WithDisabled Bool -> Maybe Bool -> WithDisabled Bool
forall a. WithDisabled a -> Maybe a -> WithDisabled a
<>? (CommandLoggingToml
toml CommandLoggingToml
-> Optic' A_Lens NoIx CommandLoggingToml (Maybe Bool) -> Maybe Bool
forall k s (is :: IxList) a.
Is k A_Getter =>
s -> Optic' k is s a -> a
^. Optic' A_Lens NoIx CommandLoggingToml (Maybe Bool)
#reportReadErrors)
          )
    }
  where
    -- Convert WithDisabled () -> WithDisabled Bool for below operation.
    argsReportReadErrors :: WithDisabled Bool
    argsReportReadErrors :: WithDisabled Bool
argsReportReadErrors = CommandLoggingArgs
args CommandLoggingArgs
-> Optic' A_Lens NoIx CommandLoggingArgs (WithDisabled ())
-> WithDisabled ()
forall k s (is :: IxList) a.
Is k A_Getter =>
s -> Optic' k is s a -> a
^. Optic' A_Lens NoIx CommandLoggingArgs (WithDisabled ())
#reportReadErrors WithDisabled () -> Bool -> WithDisabled Bool
forall (f :: Type -> Type) a b. Functor f => f a -> b -> f b
$> Bool
True

    toml :: CommandLoggingToml
toml = CommandLoggingToml
-> Maybe CommandLoggingToml -> CommandLoggingToml
forall a. a -> Maybe a -> a
fromMaybe CommandLoggingToml
defaultToml Maybe CommandLoggingToml
mToml

instance DecodeTOML CommandLoggingToml where
  tomlDecoder :: Decoder CommandLoggingToml
tomlDecoder =
    Maybe PollInterval
-> Maybe ReadSize -> Maybe Bool -> CommandLoggingToml
ConfigPhaseF 'ConfigPhaseToml PollInterval
-> ConfigPhaseF 'ConfigPhaseToml ReadSize
-> SwitchF 'ConfigPhaseToml ReportReadErrorsSwitch
-> CommandLoggingToml
forall (p :: ConfigPhase).
ConfigPhaseF p PollInterval
-> ConfigPhaseF p ReadSize
-> SwitchF p ReportReadErrorsSwitch
-> CommandLoggingP p
MkCommandLoggingP
      (Maybe PollInterval
 -> Maybe ReadSize -> Maybe Bool -> CommandLoggingToml)
-> Decoder (Maybe PollInterval)
-> Decoder (Maybe ReadSize -> Maybe Bool -> CommandLoggingToml)
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
<$> Decoder (Maybe PollInterval)
decodePollInterval
      Decoder (Maybe ReadSize -> Maybe Bool -> CommandLoggingToml)
-> Decoder (Maybe ReadSize)
-> Decoder (Maybe Bool -> CommandLoggingToml)
forall a b. Decoder (a -> b) -> Decoder a -> Decoder b
forall (f :: Type -> Type) a b.
Applicative f =>
f (a -> b) -> f a -> f b
<*> Decoder (Maybe ReadSize)
decodeReadSize
      Decoder (Maybe Bool -> CommandLoggingToml)
-> Decoder (Maybe Bool) -> Decoder CommandLoggingToml
forall a b. Decoder (a -> b) -> Decoder a -> Decoder b
forall (f :: Type -> Type) a b.
Applicative f =>
f (a -> b) -> f a -> f b
<*> Decoder (Maybe Bool)
decodeReportReadErrors

decodePollInterval :: Decoder (Maybe PollInterval)
decodePollInterval :: Decoder (Maybe PollInterval)
decodePollInterval = Decoder PollInterval -> Text -> Decoder (Maybe PollInterval)
forall a. Decoder a -> Text -> Decoder (Maybe a)
getFieldOptWith Decoder PollInterval
forall a. DecodeTOML a => Decoder a
tomlDecoder Text
"poll-interval"

decodeReadSize :: Decoder (Maybe ReadSize)
decodeReadSize :: Decoder (Maybe ReadSize)
decodeReadSize = Decoder ReadSize -> Text -> Decoder (Maybe ReadSize)
forall a. Decoder a -> Text -> Decoder (Maybe a)
getFieldOptWith Decoder ReadSize
forall a. DecodeTOML a => Decoder a
tomlDecoder Text
"read-size"

decodeReportReadErrors :: Decoder (Maybe Bool)
decodeReportReadErrors :: Decoder (Maybe Bool)
decodeReportReadErrors = Decoder Bool -> Text -> Decoder (Maybe Bool)
forall a. Decoder a -> Text -> Decoder (Maybe a)
getFieldOptWith Decoder Bool
forall a. DecodeTOML a => Decoder a
tomlDecoder Text
"report-read-errors"

-- | Creates env version from merged.
toEnv :: CommandLoggingMerged -> CommandLoggingEnv
toEnv :: CommandLoggingMerged -> CommandLoggingEnv
toEnv CommandLoggingMerged
merged =
  MkCommandLoggingP
    { pollInterval :: ConfigPhaseF 'ConfigPhaseEnv PollInterval
pollInterval = CommandLoggingMerged
merged CommandLoggingMerged
-> Optic' A_Lens NoIx CommandLoggingMerged PollInterval
-> PollInterval
forall k s (is :: IxList) a.
Is k A_Getter =>
s -> Optic' k is s a -> a
^. Optic' A_Lens NoIx CommandLoggingMerged PollInterval
#pollInterval,
      readSize :: ConfigPhaseF 'ConfigPhaseEnv ReadSize
readSize = CommandLoggingMerged
merged CommandLoggingMerged
-> Optic' A_Lens NoIx CommandLoggingMerged ReadSize -> ReadSize
forall k s (is :: IxList) a.
Is k A_Getter =>
s -> Optic' k is s a -> a
^. Optic' A_Lens NoIx CommandLoggingMerged ReadSize
#readSize,
      reportReadErrors :: SwitchF 'ConfigPhaseEnv ReportReadErrorsSwitch
reportReadErrors = CommandLoggingMerged
merged CommandLoggingMerged
-> Optic' A_Lens NoIx CommandLoggingMerged ReportReadErrorsSwitch
-> ReportReadErrorsSwitch
forall k s (is :: IxList) a.
Is k A_Getter =>
s -> Optic' k is s a -> a
^. Optic' A_Lens NoIx CommandLoggingMerged ReportReadErrorsSwitch
#reportReadErrors
    }

defaultToml :: CommandLoggingToml
defaultToml :: CommandLoggingToml
defaultToml =
  MkCommandLoggingP
    { pollInterval :: ConfigPhaseF 'ConfigPhaseToml PollInterval
pollInterval = Maybe PollInterval
ConfigPhaseF 'ConfigPhaseToml PollInterval
forall a. Maybe a
Nothing,
      readSize :: ConfigPhaseF 'ConfigPhaseToml ReadSize
readSize = Maybe ReadSize
ConfigPhaseF 'ConfigPhaseToml ReadSize
forall a. Maybe a
Nothing,
      reportReadErrors :: SwitchF 'ConfigPhaseToml ReportReadErrorsSwitch
reportReadErrors = Maybe Bool
SwitchF 'ConfigPhaseToml ReportReadErrorsSwitch
forall a. Maybe a
Nothing
    }

defaultMerged :: CommandLoggingMerged
defaultMerged :: CommandLoggingMerged
defaultMerged =
  MkCommandLoggingP
    { pollInterval :: ConfigPhaseF 'ConfigPhaseMerged PollInterval
pollInterval = ConfigPhaseF 'ConfigPhaseMerged PollInterval
PollInterval
forall a. Default a => a
def,
      readSize :: ConfigPhaseF 'ConfigPhaseMerged ReadSize
readSize = ConfigPhaseF 'ConfigPhaseMerged ReadSize
ReadSize
forall a. Default a => a
def,
      reportReadErrors :: SwitchF 'ConfigPhaseMerged ReportReadErrorsSwitch
reportReadErrors = SwitchF 'ConfigPhaseMerged ReportReadErrorsSwitch
ReportReadErrorsSwitch
forall a. Default a => a
def
    }