module arch.node.engines.pub_sub_topic_behaviour;

import arch.node.engines.pub_sub_topic_messages open;
import arch.node.engines.pub_sub_topic_config open;
import arch.node.engines.pub_sub_topic_environment open;

import arch.node.types.basics open;
import arch.node.types.identities open;
import arch.node.types.messages open;
import arch.node.types.engine open;
import arch.node.types.anoma as Anoma open;

PubSubTopicActionArguments : Type := Unit;

PubSubTopicAction : Type :=
  Action
    PubSubTopicLocalCfg
    PubSubTopicLocalState
    PubSubTopicMailboxState
    PubSubTopicTimerHandle
    PubSubTopicActionArguments
    Anoma.Msg
    Anoma.Cfg
    Anoma.Env;

PubSubTopicActionInput : Type :=
  ActionInput
    PubSubTopicLocalCfg
    PubSubTopicLocalState
    PubSubTopicMailboxState
    PubSubTopicTimerHandle
    PubSubTopicActionArguments
    Anoma.Msg;

PubSubTopicActionEffect : Type :=
  ActionEffect
    PubSubTopicLocalState
    PubSubTopicMailboxState
    PubSubTopicTimerHandle
    Anoma.Msg
    Anoma.Cfg
    Anoma.Env;

PubSubTopicActionExec : Type :=
  ActionExec
    PubSubTopicLocalCfg
    PubSubTopicLocalState
    PubSubTopicMailboxState
    PubSubTopicTimerHandle
    PubSubTopicActionArguments
    Anoma.Msg
    Anoma.Cfg
    Anoma.Env;

exampleReplyAction
  (input : PubSubTopicActionInput) : Option PubSubTopicActionEffect := TODO;

{-
let
cfg := ActionInput.cfg input;
env := ActionInput.env input;
trigger := ActionInput.trigger input;
args := ActionInput.args input;
in
case getEngineMsgFromTimestampedTrigger trigger of {
| some mkEngineMsg@{
msg := Anoma.MsgPubSubTopic (PubSubTopicMsgExampleRequest req);
sender := sender;
target := target;
mailbox := mailbox;
} :=
some mkActionEffect@{
env := env;
msgs := [
mkEngineMsg@{
sender := getEngineIDFromEngineCfg cfg;
target := sender;
mailbox := some 0;
msg :=
Anoma.MsgPubSubTopic
(PubSubTopicMsgExampleReply
(ok mkExampleReplyOk@{
argOne := ExampleRequest.argOne req;
}));
}
];
timers := [];
engines := [];
}
| _ := none
-}
exampleReplyActionLabel : PubSubTopicActionExec := Seq [exampleReplyAction];

PubSubTopicGuard : Type :=
  Guard
    PubSubTopicLocalCfg
    PubSubTopicLocalState
    PubSubTopicMailboxState
    PubSubTopicTimerHandle
    PubSubTopicActionArguments
    Anoma.Msg
    Anoma.Cfg
    Anoma.Env;

PubSubTopicGuardOutput : Type :=
  GuardOutput
    PubSubTopicLocalCfg
    PubSubTopicLocalState
    PubSubTopicMailboxState
    PubSubTopicTimerHandle
    PubSubTopicActionArguments
    Anoma.Msg
    Anoma.Cfg
    Anoma.Env;

PubSubTopicGuardEval : Type :=
  GuardEval
    PubSubTopicLocalCfg
    PubSubTopicLocalState
    PubSubTopicMailboxState
    PubSubTopicTimerHandle
    PubSubTopicActionArguments
    Anoma.Msg
    Anoma.Cfg
    Anoma.Env;

exampleReplyGuard
  (trigger : PubSubTopicTimestampedTrigger)
  (cfg : PubSubTopicCfg)
  (env : PubSubTopicEnv)
  : Option PubSubTopicGuardOutput := TODO;

{-
case getEngineMsgFromTimestampedTrigger trigger of {
| some mkEngineMsg@{
msg := Anoma.MsgPubSubTopic (PubSubTopicMsgExampleRequest req);
sender := mkPair none _; -- from local engines only (NodeID is none)
} := some mkGuardOutput@{
action := exampleReplyActionLabel;
args := [];
}
| _ := none
-}
PubSubTopicBehaviour : Type :=
  EngineBehaviour
    PubSubTopicLocalCfg
    PubSubTopicLocalState
    PubSubTopicMailboxState
    PubSubTopicTimerHandle
    PubSubTopicActionArguments
    Anoma.Msg
    Anoma.Cfg
    Anoma.Env;

module pub_sub_topic_behaviour_example;
  
  exPubSubTopicBehaviour : PubSubTopicBehaviour :=
    mkEngineBehaviour@{
      guards := First [exampleReplyGuard];
    };

end;