{-# LANGUAGE OverloadedStrings #-}

-- |
-- Description : Logging of CLI actions.
module Log
  ( -- * Types
    Log (..),

    -- ** Default Logger
    defaultLog,
  )
where

import qualified Data.Text as Text
import qualified Data.Text.IO
import Data.Text.Short (ShortText)
import qualified Data.Text.Short as ShortText
import Formatter (FormattingResult)
import qualified Formatter
import Path (File, Path, Rel, fromRelFile)
import qualified System.Console.ANSI as ANSI

-- | A logger.
--
--   All messages set to the user go through this interface.
data Log = Log
  { Log -> ShortText -> IO ()
info :: ShortText -> IO (),
    Log -> Path Rel File -> FormattingResult () -> IO ()
report :: Path Rel File -> FormattingResult () -> IO ()
  }

-- | Default logger.
defaultLog :: Log
defaultLog :: Log
defaultLog =
  Log :: (ShortText -> IO ())
-> (Path Rel File -> FormattingResult () -> IO ()) -> Log
Log
    { info :: ShortText -> IO ()
info = ShortText -> IO ()
defaultInfo,
      report :: Path Rel File -> FormattingResult () -> IO ()
report = Path Rel File -> FormattingResult () -> IO ()
defaultReport
    }

defaultInfo :: ShortText -> IO ()
defaultInfo :: ShortText -> IO ()
defaultInfo = Text -> IO ()
Data.Text.IO.putStrLn (Text -> IO ()) -> (ShortText -> Text) -> ShortText -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ShortText -> Text
ShortText.toText

defaultReport :: Path Rel File -> FormattingResult () -> IO ()
defaultReport :: Path Rel File -> FormattingResult () -> IO ()
defaultReport Path Rel File
file FormattingResult ()
result =
  case FormattingResult ()
result of
    FormattingResult ()
Formatter.NotFormatted -> () -> IO ()
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
    FormattingResult ()
Formatter.Unchanged -> do
      IO ()
boxTick
      Text -> IO ()
Data.Text.IO.putStr Text
" - "
      Path Rel File -> IO ()
putFileName Path Rel File
file
      Text -> IO ()
Data.Text.IO.putStr Text
"\n"
    Formatter.Changed () -> do
      IO ()
boxF
      Text -> IO ()
Data.Text.IO.putStr Text
" - "
      Path Rel File -> IO ()
putFileName Path Rel File
file
      Text -> IO ()
Data.Text.IO.putStr Text
"\n"
    Formatter.Error ErrorMessage
msg -> do
      IO ()
boxCross
      Text -> IO ()
Data.Text.IO.putStr Text
" - "
      Path Rel File -> IO ()
putFileName Path Rel File
file
      Text -> IO ()
Data.Text.IO.putStr Text
"\n"
      Text -> IO ()
Data.Text.IO.putStrLn (Text -> IO ()) -> (ErrorMessage -> Text) -> ErrorMessage -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ShortText -> Text
ShortText.toText (ShortText -> Text)
-> (ErrorMessage -> ShortText) -> ErrorMessage -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ErrorMessage -> ShortText
Formatter.unErrorMessage (ErrorMessage -> IO ()) -> ErrorMessage -> IO ()
forall a b. (a -> b) -> a -> b
$ ErrorMessage
msg

putFileName :: Path Rel File -> IO ()
putFileName :: Path Rel File -> IO ()
putFileName = Text -> IO ()
Data.Text.IO.putStr (Text -> IO ())
-> (Path Rel File -> Text) -> Path Rel File -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Text
Text.pack (String -> Text)
-> (Path Rel File -> String) -> Path Rel File -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Path Rel File -> String
Path.fromRelFile

boxTick :: IO ()
boxTick :: IO ()
boxTick = do
  Text -> IO ()
Data.Text.IO.putStr Text
"["
  [SGR] -> IO ()
ANSI.setSGR [ConsoleLayer -> ColorIntensity -> Color -> SGR
ANSI.SetColor ConsoleLayer
ANSI.Foreground ColorIntensity
ANSI.Vivid Color
ANSI.Green]
  Text -> IO ()
Data.Text.IO.putStr Text
"✓"
  [SGR] -> IO ()
ANSI.setSGR [SGR
ANSI.Reset]
  Text -> IO ()
Data.Text.IO.putStr Text
"]"

boxF :: IO ()
boxF :: IO ()
boxF = do
  Text -> IO ()
Data.Text.IO.putStr Text
"["
  [SGR] -> IO ()
ANSI.setSGR [ConsoleLayer -> ColorIntensity -> Color -> SGR
ANSI.SetColor ConsoleLayer
ANSI.Foreground ColorIntensity
ANSI.Vivid Color
ANSI.Yellow]
  Text -> IO ()
Data.Text.IO.putStr Text
"F"
  [SGR] -> IO ()
ANSI.setSGR [SGR
ANSI.Reset]
  Text -> IO ()
Data.Text.IO.putStr Text
"]"

boxCross :: IO ()
boxCross :: IO ()
boxCross = do
  Text -> IO ()
Data.Text.IO.putStr Text
"["
  [SGR] -> IO ()
ANSI.setSGR [ConsoleLayer -> ColorIntensity -> Color -> SGR
ANSI.SetColor ConsoleLayer
ANSI.Foreground ColorIntensity
ANSI.Vivid Color
ANSI.Red]
  Text -> IO ()
Data.Text.IO.putStr Text
"✕"
  [SGR] -> IO ()
ANSI.setSGR [SGR
ANSI.Reset]
  Text -> IO ()
Data.Text.IO.putStr Text
"]"