##! The BIFs that define the Zeek supervisor control interface.

%%{
#include "zeek/supervisor/Supervisor.h"
%%}

module Supervisor;

enum ClusterRole %{
	NONE,
	LOGGER,
	MANAGER,
	PROXY,
	WORKER,
%}

type Supervisor::ClusterEndpoint: record;
type Supervisor::Status: record;
type Supervisor::NodeConfig: record;
type Supervisor::NodeStatus: record;

function Supervisor::__status%(node: string%): Supervisor::Status
	%{
	if ( ! zeek::supervisor_mgr )
		{
		zeek::emit_builtin_error("supervisor mode not enabled");
		return zeek::make_intrusive<zeek::RecordVal>(zeek::BifType::Record::Supervisor::Status);
		}

	return zeek::supervisor_mgr->Status(node->CheckString());
	%}

function Supervisor::__create%(node: Supervisor::NodeConfig%): string
	%{
	if ( ! zeek::supervisor_mgr )
		{
		zeek::emit_builtin_error("supervisor mode not enabled");
		return zeek::make_intrusive<zeek::StringVal>("supervisor mode not enabled");
		}

	auto rval = zeek::supervisor_mgr->Create(node->AsRecordVal());
	return zeek::make_intrusive<zeek::StringVal>(rval);
	%}

function Supervisor::__destroy%(node: string%): bool
	%{
	if ( ! zeek::supervisor_mgr )
		{
		zeek::emit_builtin_error("supervisor mode not enabled");
		return zeek::val_mgr->Bool(false);
		}

	auto rval = zeek::supervisor_mgr->Destroy(node->CheckString());
	return zeek::val_mgr->Bool(rval);
	%}

function Supervisor::__restart%(node: string%): bool
	%{
	if ( ! zeek::supervisor_mgr )
		{
		zeek::emit_builtin_error("supervisor mode not enabled");
		return zeek::val_mgr->Bool(false);
		}

	auto rval = zeek::supervisor_mgr->Restart(node->CheckString());
	return zeek::val_mgr->Bool(rval);
	%}

function Supervisor::__init_cluster%(%): bool
	%{
	if ( zeek::Supervisor::ThisNode() )
		return zeek::val_mgr->Bool(zeek::Supervisor::ThisNode()->InitCluster());

	return zeek::val_mgr->Bool(false);
	%}

function Supervisor::__is_supervised%(%): bool
	%{
	return zeek::val_mgr->Bool(zeek::Supervisor::ThisNode().has_value());
	%}

function Supervisor::__node%(%): Supervisor::NodeConfig
	%{
	if ( ! zeek::Supervisor::ThisNode() )
		{
		zeek::emit_builtin_error("not a supervised process");
		const auto& rt = zeek::BifType::Record::Supervisor::NodeConfig;
		auto rval = zeek::make_intrusive<zeek::RecordVal>(rt);
		rval->AssignField("name", "<invalid>");
		return rval;
		}

	auto rval = zeek::Supervisor::ThisNode()->config.ToRecord();
	return rval;
	%}

function Supervisor::__is_supervisor%(%): bool
	%{
	return zeek::val_mgr->Bool(zeek::supervisor_mgr != nullptr);
	%}

function Supervisor::__stem_pid%(%): int
	%{
	if ( zeek::supervisor_mgr )
		return zeek::val_mgr->Int(zeek::supervisor_mgr->StemPID());

	if ( zeek::Supervisor::ThisNode() )
		return zeek::val_mgr->Int(zeek::Supervisor::ThisNode()->parent_pid);

	zeek::emit_builtin_error("supervisor mode not enabled and not a supervised node");
	return zeek::val_mgr->Int(-1);
	%}
