module System.Log.Simple (
	module System.Log.Simple.Base,
	module System.Log.Simple.Monad,
	module System.Log.Simple.Text,
	module System.Log.Simple.Stream,
	module System.Log.Simple.File,
	globalLog,
	runGlobalLog, runConsoleLog, runLogMsgs, runLogTexts
	) where
import Prelude.Unicode
import Control.Monad.IO.Class
import Control.Monad.Catch (MonadMask)
import Control.Concurrent
import Data.Maybe
import Data.Text (Text)
import System.IO.Unsafe (unsafePerformIO)
import System.Log.Simple.Base (
	Level(..), Message, Converter, Consumer, LogHandler, handler,
	LogConfig(..), defCfg, logCfg, componentCfg, Log(..),
	newLog, rootLog, getLog, subLog,
	updateLogConfig, updateLogHandlers, writeLog, stopLog)
import System.Log.Simple.Monad (
	MonadLog(..), LogT(..), noLog, withLog, runLog, sendLog,
	component, scope_, scope, scopeM, scoper, scoperM, trace,
	modifyLogConfig, modifyLogHandlers)
import System.Log.Simple.Text
import System.Log.Simple.Stream
import System.Log.Simple.File
import System.Log.Simple.Chan
globalLog ∷ Log
globalLog = unsafePerformIO $ newLog defCfg [handler text coloredConsole]
runGlobalLog ∷ LogT m a → m a
runGlobalLog = withLog globalLog
runConsoleLog ∷ (MonadIO m, MonadMask m) ⇒ LogConfig → LogT m a → m a
runConsoleLog cfg = runLog cfg [handler text coloredConsole]
runLogChan ∷ (MonadIO m, MonadMask m) ⇒ (Chan w → LogHandler) → LogConfig → LogT m a → m (a, [w])
runLogChan c cfg act = do
	ch ← liftIO newChan
	mch ← liftIO newChan
	_ ← liftIO $ forkIO $ getChanContents ch >>= mapM_ (writeChan mch . Just)
	r ← runLog cfg [c ch] act
	liftIO $ writeChan mch Nothing
	msgs ← liftIO ((catMaybes ∘ takeWhile isJust) <$> getChanContents mch)
	return (r, msgs)
runLogMsgs ∷ (MonadIO m, MonadMask m) ⇒ LogConfig → LogT m a → m (a, [Message])
runLogMsgs = runLogChan chan
runLogTexts ∷ (MonadIO m, MonadMask m) ⇒ Converter Text → LogConfig → LogT m a → m (a, [Text])
runLogTexts txt = runLogChan (handler txt ∘ chan)