{- | This is the main API module for the logger. You will generally want to import this directly.

Usage suggestions:


 -}
module LuminescentDreams.Logger (
    module X
  , LogConfig(..), LogLevel(..), Logger(..)
  , withLogger
  )
  where

import           LuminescentDreams.Logger.Types
import           LuminescentDreams.Logger.JSON        as X
import           LuminescentDreams.Logger.Standard    as X

import           Data.Monoid
import           Data.IORef                           (IORef, modifyIORef)
import qualified Data.Text                            as T
import           System.IO                            (IOMode(..), hPutStrLn, hFlush, withFile, stdout)

{- | Ordinary configurations for a file-based logger. -}
data LogConfig = Stdout LogLevel T.Text [T.Text]
               | Buffer (IORef T.Text) LogLevel T.Text [T.Text]
               | FileLog FilePath LogLevel T.Text [T.Text]


{- | Run an IO action with a log safely available. Logs will be properly closed in the case of an exception. Logging is meant to happen to a file, specified in LogConfig, so this may not be suitable if you want to log to a different resource. -}
withLogger :: LogConfig -> (Logger -> IO a) -> IO a
withLogger (Stdout level app tags) act =
  act (Logger (\m -> putStrLn (T.unpack m) >> hFlush stdout) level app tags)
withLogger (Buffer ref level app tags) act =
  act (Logger (\m -> modifyIORef ref (\buf -> buf <> m <> T.pack "\n")) level app tags)
withLogger (FileLog path level app tags) act =
  withFile path AppendMode $ \h ->
    act (Logger (\m -> hPutStrLn h (T.unpack m) >> hFlush h) level app tags)