Documentation
use crate::{Context, EventEngine, EventExt, EventOnceExt};
use std::fmt::Debug;
use std::future::Future;
use std::sync::LazyLock;
use wd_tools::AsBytes;

pub type AgentEngine = EventEngine;

pub static AGENT_ENGINE: LazyLock<AgentEngine> = LazyLock::new(EventEngine::default);

pub fn agent_engine() -> &'static AgentEngine {
    &AGENT_ENGINE
}

pub async fn register_event<T, I, E>(trigger: T, event: E)
where
    T: AsBytes,
    I: Debug + Sync + Send + 'static,
    E: EventExt<I> + Send + 'static,
{
    AGENT_ENGINE.register_event(trigger, event).await;
}

pub fn register_event_once<T, I, E>(trigger: T, event: E)
where
    T: AsBytes,
    I: Debug + Sync + Send + 'static,
    E: EventOnceExt<I> + Send + 'static,
{
    AGENT_ENGINE.register_event_once(trigger, event);
}

pub async fn invoke<T, V>(trigger: T, input: V) -> anyhow::Result<Context>
where
    T: AsBytes,
    V: Debug + Sync + Send + 'static,
{
    AGENT_ENGINE.invoke(trigger, input).await
}

pub fn launch<T, V>(trigger: T, input: V)
where
    T: AsBytes + Send + 'static,
    V: Debug + Sync + Send + 'static,
{
    AGENT_ENGINE.launch(trigger, input);
}

pub fn launch_fn<T, V>(trigger: T, input: V, over_fn: impl FnOnce(Context) + Send + 'static)
where
    T: AsBytes + Send + 'static,
    V: Debug + Sync + Send + 'static,
{
    AGENT_ENGINE.launch_fn(trigger, input, over_fn);
}

pub fn launch_fut<T, V, F>(
    trigger: T,
    input: V,
    over_fn: impl FnOnce(Context) -> F + Send + 'static,
) where
    T: AsBytes + Send + 'static,
    V: Debug + Sync + Send + 'static,
    F: Future<Output = ()> + Send + 'static,
{
    AGENT_ENGINE.launch_fut(trigger, input, over_fn);
}