module Shrun.Configuration.Data.FileLogging.FileSizeMode
  ( FileSizeMode (..),
    parseFileSizeMode,
    fileSizeModeMeta,
  )
where

import Data.Bytes (Conversion (convert_))
import Data.Bytes.Size (Size (M))
import Data.Char qualified as Ch
import Data.Text qualified as T
import Shrun.Configuration.Default (Default (def))
import Shrun.Prelude
import Shrun.Utils qualified as U
import Shrun.Utils qualified as Utils

-- | Determines what to do if the log file surpasses the given size
-- threshold.
data FileSizeMode
  = -- | Print a warning.
    FileSizeModeWarn (Bytes B Natural)
  | -- | Delete the file.
    FileSizeModeDelete (Bytes B Natural)
  | -- | Does nothing.
    FileSizeModeNothing
  deriving stock (FileSizeMode -> FileSizeMode -> Bool
(FileSizeMode -> FileSizeMode -> Bool)
-> (FileSizeMode -> FileSizeMode -> Bool) -> Eq FileSizeMode
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: FileSizeMode -> FileSizeMode -> Bool
== :: FileSizeMode -> FileSizeMode -> Bool
$c/= :: FileSizeMode -> FileSizeMode -> Bool
/= :: FileSizeMode -> FileSizeMode -> Bool
Eq, Int -> FileSizeMode -> ShowS
[FileSizeMode] -> ShowS
FileSizeMode -> String
(Int -> FileSizeMode -> ShowS)
-> (FileSizeMode -> String)
-> ([FileSizeMode] -> ShowS)
-> Show FileSizeMode
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> FileSizeMode -> ShowS
showsPrec :: Int -> FileSizeMode -> ShowS
$cshow :: FileSizeMode -> String
show :: FileSizeMode -> String
$cshowList :: [FileSizeMode] -> ShowS
showList :: [FileSizeMode] -> ShowS
Show)

instance DecodeTOML FileSizeMode where
  tomlDecoder :: Decoder FileSizeMode
tomlDecoder = Decoder Text -> Decoder FileSizeMode
forall (m :: Type -> Type). MonadFail m => m Text -> m FileSizeMode
parseFileSizeMode Decoder Text
forall a. DecodeTOML a => Decoder a
tomlDecoder

instance Pretty FileSizeMode where
  pretty :: forall ann. FileSizeMode -> Doc ann
pretty = \case
    FileSizeModeWarn Bytes 'B Natural
b -> Doc ann
"warn " Doc ann -> Doc ann -> Doc ann
forall a. Semigroup a => a -> a -> a
<> Bytes 'B Natural -> Doc ann
forall a (s :: Size) ann.
(BaseFormatter a ~ IntegralFormatter, Fromℤ a, MGroup a, Normed a,
 Ord a, PrintfArg a, SingI s) =>
Bytes s a -> Doc ann
prettyBytesInt Bytes 'B Natural
b
    FileSizeModeDelete Bytes 'B Natural
b -> Doc ann
"delete " Doc ann -> Doc ann -> Doc ann
forall a. Semigroup a => a -> a -> a
<> Bytes 'B Natural -> Doc ann
forall a (s :: Size) ann.
(BaseFormatter a ~ IntegralFormatter, Fromℤ a, MGroup a, Normed a,
 Ord a, PrintfArg a, SingI s) =>
Bytes s a -> Doc ann
prettyBytesInt Bytes 'B Natural
b
    FileSizeMode
FileSizeModeNothing -> Doc ann
"off"

parseFileSizeMode :: (MonadFail m) => m Text -> m FileSizeMode
parseFileSizeMode :: forall (m :: Type -> Type). MonadFail m => m Text -> m FileSizeMode
parseFileSizeMode m Text
getTxt = do
  Text
txt <- m Text
getTxt
  if Text
txt Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== Text
"off"
    then FileSizeMode -> m FileSizeMode
forall a. a -> m a
forall (f :: Type -> Type) a. Applicative f => a -> f a
pure FileSizeMode
FileSizeModeNothing
    else do
      let (Text
m, Text
byteTxt) = (Char -> Bool) -> Text -> (Text, Text)
T.break Char -> Bool
Ch.isSpace Text
txt
      Bytes 'B Natural -> FileSizeMode
cons <- case Text
m of
        Text
"warn" -> (Bytes 'B Natural -> FileSizeMode)
-> m (Bytes 'B Natural -> FileSizeMode)
forall a. a -> m a
forall (f :: Type -> Type) a. Applicative f => a -> f a
pure Bytes 'B Natural -> FileSizeMode
FileSizeModeWarn
        Text
"delete" -> (Bytes 'B Natural -> FileSizeMode)
-> m (Bytes 'B Natural -> FileSizeMode)
forall a. a -> m a
forall (f :: Type -> Type) a. Applicative f => a -> f a
pure Bytes 'B Natural -> FileSizeMode
FileSizeModeDelete
        Text
bad ->
          String -> m (Bytes 'B Natural -> FileSizeMode)
forall a. String -> m a
forall (m :: Type -> Type) a. MonadFail m => String -> m a
fail
            (String -> m (Bytes 'B Natural -> FileSizeMode))
-> String -> m (Bytes 'B Natural -> FileSizeMode)
forall a b. (a -> b) -> a -> b
$ String -> (Bool, [String]) -> ShowS
forall a. (IsString a, Monoid a) => a -> (Bool, [a]) -> a -> a
Utils.fmtUnrecognizedError
              String
"size mode"
              (Bool, [String])
forall a. IsString a => (Bool, [a])
fileSizeModeMeta
              (Text -> String
unpack Text
bad)
      case Text -> Either Text (Bytes 'B Natural)
U.parseByteText Text
byteTxt of
        Right Bytes 'B Natural
b -> FileSizeMode -> m FileSizeMode
forall a. a -> m a
forall (f :: Type -> Type) a. Applicative f => a -> f a
pure (FileSizeMode -> m FileSizeMode) -> FileSizeMode -> m FileSizeMode
forall a b. (a -> b) -> a -> b
$ Bytes 'B Natural -> FileSizeMode
cons Bytes 'B Natural
b
        Left Text
err -> String -> m FileSizeMode
forall a. String -> m a
forall (m :: Type -> Type) a. MonadFail m => String -> m a
fail (String -> m FileSizeMode) -> String -> m FileSizeMode
forall a b. (a -> b) -> a -> b
$ String
"Could not parse --file-log-size-mode size: " String -> ShowS
forall a. Semigroup a => a -> a -> a
<> Text -> String
unpack Text
err
{-# INLINEABLE parseFileSizeMode #-}

instance Default FileSizeMode where
  def :: FileSizeMode
def = Bytes 'B Natural -> FileSizeMode
FileSizeModeWarn (Bytes 'B Natural -> FileSizeMode)
-> Bytes 'B Natural -> FileSizeMode
forall a b. (a -> b) -> a -> b
$ forall a (t :: Size). (Conversion a, SingI t) => a -> Converted t a
convert_ @_ @B Bytes 'M Natural
defBytes
    where
      defBytes :: Bytes M Natural
      defBytes :: Bytes 'M Natural
defBytes = Natural -> Bytes 'M Natural
forall (s :: Size) n. n -> Bytes s n
MkBytes Natural
50

fileSizeModeMeta :: (IsString a) => Tuple2 Bool (List a)
fileSizeModeMeta :: forall a. IsString a => (Bool, [a])
fileSizeModeMeta = (Bool
True, [a
"delete BYTES", a
"warn BYTES"])