content: module Eventful.ReadModel.Memory
    ( memoryReadModel
    ) where
  
  import Control.Concurrent.STM
  import Control.Monad.IO.Class
  import Safe (maximumDef)
  
  import Eventful.ReadModel.Class
  import Eventful.Store.Class
  
  data MemoryReadModelData modeldata
    = MemoryReadModelData
    { memoryReadModelDataLatestSequenceNumber :: SequenceNumber
    , _memoryReadModelDataValue :: modeldata
    } deriving (Show)
  
  -- | Creates a read model that wraps some pure data in a TVar and manages the
  -- latest sequence number for you.
  memoryReadModel
    :: (MonadIO m)
    => modeldata
    -> (modeldata -> [GlobalStreamEvent serialized] -> m modeldata)
    -> IO (ReadModel (TVar (MemoryReadModelData modeldata)) serialized m)
  memoryReadModel initialValue handleEvents = do
    tvar <- newTVarIO $ MemoryReadModelData (-1) initialValue
    return $ ReadModel tvar getLatestSequence handleTVarEvents
    where
      getLatestSequence tvar' = liftIO $ memoryReadModelDataLatestSequenceNumber <$> readTVarIO tvar'
      handleTVarEvents tvar' events = do
        (MemoryReadModelData latestSeq modelData) <- liftIO $ readTVarIO tvar'
        let latestSeq' = maximumDef latestSeq (streamEventPosition <$> events)
        modelData' <- handleEvents modelData events
        liftIO . atomically . writeTVar tvar' $ MemoryReadModelData latestSeq' modelData'
  