{-# LANGUAGE OverloadedStrings #-}

module Logging.Types.Level ( Level(..) ) where

import           Data.Default
import           Data.List    (stripPrefix)
import           Data.String
import           Text.Format


-- |'Level' also known as severity, a higher 'Level' means a bigger 'Int'.
--
-- There are 5 common severity levels:
--
-- [@DEBUG@] Level 10
-- [@INFO@] Level 20
-- [@WARN@] Level 30
-- [@ERROR@] Level 40
-- [@FATAL@] Level 50
--
-- >>> :set -XOverloadedStrings
-- >>> "DEBUG" :: Level
-- DEBUG
-- >>> "DEBUG" == (Level 10)
-- True
--
newtype Level = Level Int deriving (Eq, Ord)

instance FormatArg Level where
  formatArg = formatArg . show

instance Show Level where
  show (Level 0)  = "NOTSET"
  show (Level 10) = "DEBUG"
  show (Level 20) = "INFO"
  show (Level 30) = "WARN"
  show (Level 40) = "ERROR"
  show (Level 50) = "FATAL"
  show (Level v)  = "LEVEL " ++ show v

instance Read Level where
  readsPrec _ "NOTSET" = [(Level 0, "")]
  readsPrec _ "DEBUG"  = [(Level 10, "")]
  readsPrec _ "INFO"   = [(Level 20, "")]
  readsPrec _ "WARN"   = [(Level 30, "")]
  readsPrec _ "ERROR"  = [(Level 40, "")]
  readsPrec _ "FATAL"  = [(Level 50, "")]
  readsPrec _ s       = case (stripPrefix "LEVEL " s) of
                          Just v -> [(Level (read v), "")]
                          _      -> []

instance IsString Level where
  fromString = read

instance Enum Level where
  toEnum = Level
  fromEnum (Level v) = v

instance Default Level where
  def = "NOTSET"