module Yore.Log (Yore.Log.error, info) where

import Control.Monad.IO.Class (MonadIO (..))
import Data.Time (ZonedTime, getZonedTime)
import Data.Time.Format (defaultTimeLocale, formatTime)
import GHC.Stack (HasCallStack, SrcLoc (..), callStack, getCallStack)
import Text.Printf (printf)

info :: (HasCallStack, MonadIO m) => String -> m ()
info = doLog "INF"

error :: (HasCallStack, MonadIO m) => String -> m ()
error = doLog "ERR"

doLog :: (HasCallStack, MonadIO m) => String -> String -> m ()
doLog level msg = liftIO $ do
  now <- getZonedTime
  let location = getLocation $ getCallStack callStack
  printf "(%s) (%s) (%s) %s\n" (iso8601Show now) level location msg
  where
    getLocation :: [(String, SrcLoc)] -> String
    -- First entry is always a function from this module, skip it
    getLocation (_ : (_, srcLoc) : _) = printf "%s:%d" (srcLocFile srcLoc) (srcLocStartLine srcLoc)
    getLocation _ = ""

-- | Unlike 'Data.Time.Format.ISO8601.iso8601Show', this function
-- aligns the second decimals. This is purely for asthetic reasons.
iso8601Show :: ZonedTime -> String
iso8601Show = formatTime defaultTimeLocale "%FT%T%02Q%Ez"
