module Shrun.Configuration.Data.FileLogging.FileSizeMode
  ( FileSizeMode (..),
    parseFileSizeMode,
    expectedStr,
  )
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

-- | 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

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
"nothing"
    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] -> String
forall a. Monoid a => [a] -> a
mconcat
              [ String
"Expected file-log-size-mode as one of ",
                String
expectedStr,
                String
" received: '",
                Text -> String
unpack Text
bad,
                String
"'"
              ]
      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

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
$ Proxy 'B -> Bytes 'M Natural -> Converted 'B (Bytes 'M Natural)
forall a (t :: Size).
(Conversion a, SingSize t) =>
Proxy t -> a -> Converted t a
forall (t :: Size).
SingSize t =>
Proxy t -> Bytes 'M Natural -> Converted t (Bytes 'M Natural)
convert (forall {k} (t :: k). Proxy t
forall (t :: Size). Proxy t
Proxy @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

expectedStr :: String
expectedStr :: String
expectedStr = String
"(warn BYTES | delete BYTES | nothing)"