-- |Agent Interpreter for Network, Internal
module Helic.Interpreter.AgentNet where

import Polysemy.Http (Manager)
import qualified Polysemy.Log as Log

import Helic.Data.Event (Event (source))
import Helic.Data.NetConfig (NetConfig (NetConfig))
import Helic.Effect.Agent (Agent (Update), AgentNet, agentIdNet)
import Helic.Interpreter (interpreting)
import Helic.Net.Client (sendTo)

-- |Interpret 'Agent' using remote hosts as targets.
-- This also starts the HTTP server that listens to network events, which are used both for remote hosts and CLI
-- events.
interpretAgentNet ::
  Members [Manager, Reader NetConfig] r =>
  Members [Log, Interrupt, Race, Resource, Async, Embed IO, Final IO] r =>
  InterpreterFor (Tagged AgentNet Agent) r
interpretAgentNet :: InterpreterFor (Tagged AgentNet Agent) r
interpretAgentNet Sem (Tagged AgentNet Agent : r) a
sem =
  Sem (Agent : r) a
-> (forall (r0 :: EffectRow) x. Agent (Sem r0) x -> Sem r x)
-> Sem r a
forall (e :: Effect) (r :: EffectRow) a.
FirstOrder e "interpret" =>
Sem (e : r) a
-> (forall (r0 :: EffectRow) x. e (Sem r0) x -> Sem r x) -> Sem r a
interpreting (Sem (Tagged AgentNet Agent : r) a -> Sem (Agent : r) a
forall k1 (k2 :: k1) (e :: Effect) (r :: EffectRow) a.
Sem (Tagged k2 e : r) a -> Sem (e : r) a
untag Sem (Tagged AgentNet Agent : r) a
sem) \case
    Update Event
e -> do
      NetConfig Maybe Int
_ Maybe Timeout
timeout Maybe [Host]
hosts <- Sem r NetConfig
forall i (r :: EffectRow). Member (Reader i) r => Sem r i
ask
      [Host] -> (Host -> Sem r ()) -> Sem r ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
t a -> (a -> f b) -> f ()
for_ (Maybe [Host] -> [Host]
forall (t :: * -> *) m. (Foldable t, Monoid m) => t m -> m
fold Maybe [Host]
hosts) \ Host
host ->
        (Text -> Sem r ())
-> (() -> Sem r ()) -> Either Text () -> Sem r ()
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either Text -> Sem r ()
forall (r :: EffectRow).
(HasCallStack, Member Log r) =>
Text -> Sem r ()
Log.debug () -> Sem r ()
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Either Text () -> Sem r ()) -> Sem r (Either Text ()) -> Sem r ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Sem (Error Text : r) () -> Sem r (Either Text ())
forall e (r :: EffectRow) a.
Sem (Error e : r) a -> Sem r (Either e a)
runError (Maybe Timeout -> Host -> Event -> Sem (Error Text : r) ()
forall (r :: EffectRow).
Members '[Manager, Log, Race, Error Text, Embed IO] r =>
Maybe Timeout -> Host -> Event -> Sem r ()
sendTo Maybe Timeout
timeout Host
host Event
e { $sel:source:Event :: AgentId
source = AgentId
agentIdNet })