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) <- (event -> StageRIO st ())
-> StageRIO st (ReleaseKey, Sink event st)
forall event rs.
(event -> StageRIO rs ())
-> StageRIO rs (ReleaseKey, Sink event rs)
Sink.spawn event -> StageRIO st ()
handleEvent

  ReleaseKey
key <- [StageRIO st ReleaseKey] -> StageRIO st ReleaseKey
forall st. [StageRIO st ReleaseKey] -> StageRIO st ReleaseKey
registerMany ([StageRIO st ReleaseKey] -> StageRIO st ReleaseKey)
-> [StageRIO st ReleaseKey] -> StageRIO st ReleaseKey
forall a b. (a -> b) -> a -> b
$
    ReleaseKey -> StageRIO st ReleaseKey
forall (f :: * -> *) a. Applicative f => a -> f a
pure ReleaseKey
sinkKey StageRIO st ReleaseKey
-> [StageRIO st ReleaseKey] -> [StageRIO st ReleaseKey]
forall a. a -> [a] -> [a]
:
    ((Sink event st -> StageRIO st ReleaseKey)
 -> StageRIO st ReleaseKey)
-> [Sink event st -> StageRIO st ReleaseKey]
-> [StageRIO st ReleaseKey]
forall a b. (a -> b) -> [a] -> [b]
map ((Sink event st -> StageRIO st ReleaseKey)
-> Sink event st -> StageRIO st ReleaseKey
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 =
  [StageRIO st ReleaseKey] -> RIO (App GlobalHandles st) [ReleaseKey]
forall (t :: * -> *) (f :: * -> *) a.
(Traversable t, Applicative f) =>
t (f a) -> f (t a)
sequenceA [StageRIO st ReleaseKey]
actions RIO (App GlobalHandles st) [ReleaseKey]
-> ([ReleaseKey] -> StageRIO st ReleaseKey)
-> StageRIO st ReleaseKey
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>=
    IO () -> StageRIO st ReleaseKey
forall (m :: * -> *). MonadResource m => IO () -> m ReleaseKey
Resource.register (IO () -> StageRIO st ReleaseKey)
-> ([ReleaseKey] -> IO ())
-> [ReleaseKey]
-> StageRIO st ReleaseKey
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (ReleaseKey -> IO ()) -> [ReleaseKey] -> IO ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
(a -> f b) -> t a -> f ()
traverse_ ReleaseKey -> IO ()
forall (m :: * -> *). MonadIO m => ReleaseKey -> m ()
Resource.release