{-# LANGUAGE CPP #-}

module Blammo.Logging.Test
  ( LoggedMessages
  , LoggedMessage(..)
  , newLoggedMessages
  , appendLogStr
  , getLoggedMessages
  ) where

import Prelude

import Control.Monad.IO.Class (MonadIO(..))
import Control.Monad.Logger.Aeson (LoggedMessage(..))
import Data.Aeson (eitherDecodeStrict)
import Data.DList (DList)
import qualified Data.DList as DList
import System.Log.FastLogger (LogStr, fromLogStr)
import UnliftIO.IORef

newtype LoggedMessages = LoggedMessages
  { LoggedMessages -> IORef (DList LogStr)
_unLoggedMessages :: IORef (DList LogStr)
  }

newLoggedMessages :: MonadIO m => m LoggedMessages
newLoggedMessages :: m LoggedMessages
newLoggedMessages = IORef (DList LogStr) -> LoggedMessages
LoggedMessages (IORef (DList LogStr) -> LoggedMessages)
-> m (IORef (DList LogStr)) -> m LoggedMessages
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> DList LogStr -> m (IORef (DList LogStr))
forall (m :: * -> *) a. MonadIO m => a -> m (IORef a)
newIORef DList LogStr
forall a. DList a
DList.empty

appendLogStr :: MonadIO m => LoggedMessages -> LogStr -> m ()
appendLogStr :: LoggedMessages -> LogStr -> m ()
appendLogStr (LoggedMessages IORef (DList LogStr)
ref) LogStr
str =
  IORef (DList LogStr)
-> (DList LogStr -> (DList LogStr, ())) -> m ()
forall (m :: * -> *) a b.
MonadIO m =>
IORef a -> (a -> (a, b)) -> m b
atomicModifyIORef' IORef (DList LogStr)
ref ((DList LogStr -> (DList LogStr, ())) -> m ())
-> (DList LogStr -> (DList LogStr, ())) -> m ()
forall a b. (a -> b) -> a -> b
$ \DList LogStr
x -> (DList LogStr -> LogStr -> DList LogStr
forall a. DList a -> a -> DList a
DList.snoc DList LogStr
x LogStr
str, ())

getLoggedMessages :: MonadIO m => LoggedMessages -> m [Either String LoggedMessage]
getLoggedMessages :: LoggedMessages -> m [Either String LoggedMessage]
getLoggedMessages (LoggedMessages IORef (DList LogStr)
ref) =
  (LogStr -> Either String LoggedMessage)
-> [LogStr] -> [Either String LoggedMessage]
forall a b. (a -> b) -> [a] -> [b]
map (ByteString -> Either String LoggedMessage
forall a. FromJSON a => ByteString -> Either String a
eitherDecodeStrict (ByteString -> Either String LoggedMessage)
-> (LogStr -> ByteString) -> LogStr -> Either String LoggedMessage
forall b c a. (b -> c) -> (a -> b) -> a -> c
. LogStr -> ByteString
fromLogStr) ([LogStr] -> [Either String LoggedMessage])
-> (DList LogStr -> [LogStr])
-> DList LogStr
-> [Either String LoggedMessage]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. DList LogStr -> [LogStr]
forall a. DList a -> [a]
DList.toList (DList LogStr -> [Either String LoggedMessage])
-> m (DList LogStr) -> m [Either String LoggedMessage]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IORef (DList LogStr) -> m (DList LogStr)
forall (m :: * -> *) a. MonadIO m => IORef a -> m a
readIORef IORef (DList LogStr)
ref