{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards   #-}

module Logging.Global.Internal
  ( log
  , run
  ) where


import           Control.Exception
import           Control.Monad
import           Control.Monad.IO.Class
import           Data.IORef
import           GHC.Conc
import           Prelude                hiding (log)
import           System.IO.Unsafe

import qualified Logging.Monad.Internal as M
import           Logging.Types

{-# NOINLINE ref #-}
ref :: IORef Manager
ref = unsafePerformIO $ newIORef undefined


log :: MonadIO m
     => Logger -> Level -> String -> (String, String, String, Int)
     -> m ()
log logger level message location = liftIO $ do
  manager <- readIORef ref
  M.runLoggingT (M.log logger level message location) manager


run :: Manager -> IO a -> IO a
run manager@Manager{..} io = do
    oldHandler <- getUncaughtExceptionHandler
    when catchUncaughtException $ setUncaughtExceptionHandler logException
    bracket_ (initialize manager >> atomicWriteIORef ref manager)
             (terminate manager >> setUncaughtExceptionHandler oldHandler)
             io
  where
    unknownLoc = ("unknown file", "unknown package", "unknown module", 0)

    logException :: SomeException -> IO ()
    logException e = log "" "ERROR" (show e) unknownLoc