module Engine.Events
  ( Sink(..)
  , spawn
  , registerMany
  ) where

import RIO

import UnliftIO.Resource (ReleaseKey)
import UnliftIO.Resource qualified as Resource

import Engine.Events.Sink (Sink)
import Engine.Events.Sink qualified as Sink
import Engine.Types (StageRIO)

spawn
  :: (event -> StageRIO st ())
  -> [Sink event st -> StageRIO st ReleaseKey]
  -> StageRIO st (ReleaseKey, Sink event st)
spawn :: forall event st.
(event -> StageRIO st ())
-> [Sink event st -> StageRIO st ReleaseKey]
-> StageRIO st (ReleaseKey, Sink event st)
spawn event -> StageRIO st ()
handleEvent [Sink event st -> StageRIO st ReleaseKey]
sources = do
  (ReleaseKey
sinkKey, Sink event st
sink) <- forall event rs.
(event -> StageRIO rs ())
-> StageRIO rs (ReleaseKey, Sink event rs)
Sink.spawn event -> StageRIO st ()
handleEvent

  ReleaseKey
key <- forall st. [StageRIO st ReleaseKey] -> StageRIO st ReleaseKey
registerMany forall a b. (a -> b) -> a -> b
$
    forall (f :: * -> *) a. Applicative f => a -> f a
pure ReleaseKey
sinkKey forall a. a -> [a] -> [a]
:
    forall a b. (a -> b) -> [a] -> [b]
map (forall a b. (a -> b) -> a -> b
$ Sink event st
sink) [Sink event st -> StageRIO st ReleaseKey]
sources

  pure (ReleaseKey
key, Sink event st
sink)

registerMany :: [StageRIO st ReleaseKey] -> StageRIO st ReleaseKey
registerMany :: forall st. [StageRIO st ReleaseKey] -> StageRIO st ReleaseKey
registerMany [StageRIO st ReleaseKey]
actions =
  forall (t :: * -> *) (f :: * -> *) a.
(Traversable t, Applicative f) =>
t (f a) -> f (t a)
sequenceA [StageRIO st ReleaseKey]
actions forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>=
    forall (m :: * -> *). MonadResource m => IO () -> m ReleaseKey
Resource.register forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
(a -> f b) -> t a -> f ()
traverse_ forall (m :: * -> *). MonadIO m => ReleaseKey -> m ()
Resource.release