use anyhow::Result;
use arcstr::ArcStr;
use fxhash::FxHashMap;
use graphix_compiler::{env::Env, ExecCtx};
use graphix_package::{CustomDisplay, IndexSet, MainThreadHandle, Package};
use graphix_rt::{CompExp, GXExt, GXHandle, GXRt};
use netidx_core::path::Path;
use tokio::sync::oneshot;
pub(crate) struct RegisterResult {
pub root: ArcStr,
pub main_program: Option<&'static str>,
}
pub(crate) fn register<X: GXExt>(
ctx: &mut ExecCtx<GXRt<X>, X::UserEvent>,
modules: &mut FxHashMap<Path, ArcStr>,
) -> Result<RegisterResult> {
let mut root_mods = IndexSet::new();
graphix_package_core::P::register(ctx, modules, &mut root_mods)?;
graphix_package_array::P::register(ctx, modules, &mut root_mods)?;
graphix_package_list::P::register(ctx, modules, &mut root_mods)?;
graphix_package_str::P::register(ctx, modules, &mut root_mods)?;
graphix_package_map::P::register(ctx, modules, &mut root_mods)?;
graphix_package_sys::P::register(ctx, modules, &mut root_mods)?;
graphix_package_args::P::register(ctx, modules, &mut root_mods)?;
graphix_package_http::P::register(ctx, modules, &mut root_mods)?;
graphix_package_json::P::register(ctx, modules, &mut root_mods)?;
graphix_package_toml::P::register(ctx, modules, &mut root_mods)?;
graphix_package_pack::P::register(ctx, modules, &mut root_mods)?;
graphix_package_xls::P::register(ctx, modules, &mut root_mods)?;
graphix_package_sqlite::P::register(ctx, modules, &mut root_mods)?;
graphix_package_db::P::register(ctx, modules, &mut root_mods)?;
graphix_package_hbs::P::register(ctx, modules, &mut root_mods)?;
graphix_package_re::P::register(ctx, modules, &mut root_mods)?;
graphix_package_rand::P::register(ctx, modules, &mut root_mods)?;
graphix_package_tui::P::register(ctx, modules, &mut root_mods)?;
#[cfg(feature = "gui")]
graphix_package_gui::P::register(ctx, modules, &mut root_mods)?;
let mut parts = Vec::new();
for name in &root_mods {
if name == "core" {
parts.push(format!("mod core;\nuse core"));
} else {
parts.push(format!("mod {name}"));
}
}
Ok(RegisterResult { root: ArcStr::from(parts.join(";\n")), main_program: None })
}
pub(crate) struct Cdc<X: GXExt> {
pub stop: oneshot::Receiver<()>,
pub custom: Box<dyn CustomDisplay<X>>,
}
pub(crate) enum CustomResult<X: GXExt> {
Custom(Cdc<X>),
NotCustom(CompExp<X>),
}
pub(crate) async fn maybe_init_custom<X: GXExt>(
gx: &GXHandle<X>,
env: &Env,
e: CompExp<X>,
run_on_main: &MainThreadHandle,
) -> Result<CustomResult<X>> {
macro_rules! try_pkg {
($pkg:path) => {
if <$pkg>::is_custom(gx, env, &e) {
let (tx, rx) = oneshot::channel();
return <$pkg>::init_custom(gx, env, tx, e, run_on_main.clone())
.await
.map(|custom| CustomResult::Custom(Cdc { stop: rx, custom }));
}
};
}
try_pkg!(graphix_package_core::P);
try_pkg!(graphix_package_array::P);
try_pkg!(graphix_package_list::P);
try_pkg!(graphix_package_str::P);
try_pkg!(graphix_package_map::P);
try_pkg!(graphix_package_sys::P);
try_pkg!(graphix_package_args::P);
try_pkg!(graphix_package_http::P);
try_pkg!(graphix_package_json::P);
try_pkg!(graphix_package_toml::P);
try_pkg!(graphix_package_pack::P);
try_pkg!(graphix_package_xls::P);
try_pkg!(graphix_package_sqlite::P);
try_pkg!(graphix_package_db::P);
try_pkg!(graphix_package_hbs::P);
try_pkg!(graphix_package_re::P);
try_pkg!(graphix_package_rand::P);
try_pkg!(graphix_package_tui::P);
#[cfg(feature = "gui")]
try_pkg!(graphix_package_gui::P);
Ok(CustomResult::NotCustom(e))
}