module Log.Internal.Logger (
    Logger(..)
  , execLogger
  , waitForLogger
  , shutdownLogger
  , withLogger
  ) where
import Data.Semigroup
import Control.Exception
import Prelude
import Log.Data
data Logger = Logger {
  loggerWriteMessage :: !(LogMessage -> IO ()) 
, loggerWaitForWrite :: !(IO ())
                     
                     
                     
, loggerShutdown     :: !(IO ())
                     
                     
                     
}
execLogger :: Logger -> LogMessage -> IO ()
execLogger Logger{..} = loggerWriteMessage
waitForLogger :: Logger -> IO ()
waitForLogger Logger{..} = loggerWaitForWrite
shutdownLogger :: Logger -> IO ()
shutdownLogger Logger{..} = loggerShutdown
withLogger :: Logger -> (Logger -> IO r) -> IO r
withLogger logger act = act logger `finally` cleanup
  where
    cleanup = waitForLogger logger >> shutdownLogger logger
instance Semigroup Logger where
  l1 <> l2 = Logger {
    loggerWriteMessage = \msg -> do
      loggerWriteMessage l1 msg
      loggerWriteMessage l2 msg
  , loggerWaitForWrite = do
      loggerWaitForWrite l1
      loggerWaitForWrite l2
  , loggerShutdown     = do
      loggerShutdown l1
      loggerShutdown l2
  }
instance Monoid Logger where
  mempty  = Logger (const $ return ()) (return ()) (return ())
  mappend = (<>)