-- |Simple Agent Interpreter, Internal
module Helic.Interpreter.Agent where

import GHC.Records (HasField)

import Helic.Data.Event (Event)
import Helic.Effect.Agent (Agent (Update))
import Helic.Interpreter (interpreting)

-- |Interpret 'Agent' with an action.
interpretAgent ::
   id r .
  (Event -> Sem r ()) ->
  InterpreterFor (Agent @@ id) r
interpretAgent :: forall {k} (id :: k) (r :: EffectRow).
(Event -> Sem r ()) -> InterpreterFor (Agent @@ id) r
interpretAgent Event -> Sem r ()
handle Sem ((Agent @@ id) : r) a
sem =
  forall (e :: (* -> *) -> * -> *) (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 (forall {k1} (k2 :: k1) (e :: (* -> *) -> * -> *) (r :: EffectRow)
       a.
Sem (Tagged k2 e : r) a -> Sem (e : r) a
untag Sem ((Agent @@ id) : r) a
sem) \case
    Update Event
e ->
      Event -> Sem r ()
handle Event
e

-- | Interpret 'Agent' by doing nothing.
interpretAgentNull :: InterpreterFor (Agent @@ id) r
interpretAgentNull :: forall {k} (id :: k) (r :: EffectRow).
InterpreterFor (Agent @@ id) r
interpretAgentNull = forall {k} (id :: k) (r :: EffectRow).
(Event -> Sem r ()) -> InterpreterFor (Agent @@ id) r
interpretAgent (forall a b. a -> b -> a
const forall (f :: * -> *). Applicative f => f ()
unit)

-- | Interpret 'Agent' using the supplied interpreter unless the first argument is 'Just False', in which case run the
-- dummy interpreter.
interpretAgentIf ::
  HasField "enable" conf (Maybe Bool) =>
  Member (Reader conf) r =>
  InterpreterFor Agent r ->
  InterpreterFor (Agent @@ id) r
interpretAgentIf :: forall {k} conf (r :: EffectRow) (id :: k).
(HasField "enable" conf (Maybe Bool), Member (Reader conf) r) =>
InterpreterFor Agent r -> InterpreterFor (Agent @@ id) r
interpretAgentIf InterpreterFor Agent r
int Sem ((Agent @@ id) : r) a
sem = do
  conf
conf <- forall i (r :: EffectRow). Member (Reader i) r => Sem r i
ask
  if | Just Bool
False <- conf
conf.enable -> forall {k} (id :: k) (r :: EffectRow).
InterpreterFor (Agent @@ id) r
interpretAgentNull Sem ((Agent @@ id) : r) a
sem
     | Bool
otherwise -> InterpreterFor Agent r
int (forall {k1} (k2 :: k1) (e :: (* -> *) -> * -> *) (r :: EffectRow)
       a.
Sem (Tagged k2 e : r) a -> Sem (e : r) a
untag Sem ((Agent @@ id) : r) a
sem)