use std::any::TypeId;
use std::collections::HashMap;
use bevy::ecs::system::SystemParam;
use bevy::prelude::*;
use serde::Serialize;
use ts_rs::TS;
use crate::bridge::OutboundResource;
use crate::protocol::Outbound;
use crate::registry::{NamedEntry, register_entry};
use crate::ts_codegen::TsCollector;
pub trait ReactEvent: Serialize + TS + Send + Sync + 'static {
const NAME: &'static str;
}
#[derive(SystemParam)]
pub struct ReactEvents<'w> {
out: Res<'w, OutboundResource>,
}
impl ReactEvents<'_> {
pub fn send<E: ReactEvent>(&self, event: &E) {
match serde_json::to_value(event) {
Ok(value) => {
let _ = self.out.0.send(Outbound::Event {
name: E::NAME.to_string(),
value,
});
}
Err(e) => error!("serialize react event {:?}: {e}", E::NAME),
}
}
}
pub(crate) struct EventRegistration {
type_id: TypeId,
pub(crate) ts_name: fn() -> String,
pub(crate) ts_collect: fn(&mut TsCollector),
}
#[derive(Resource, Default)]
pub(crate) struct ReactEventRegistry {
pub(crate) handlers: HashMap<&'static str, EventRegistration>,
}
impl NamedEntry for EventRegistration {
fn type_id(&self) -> TypeId {
self.type_id
}
}
impl ReactEventRegistry {
pub(crate) fn register<E: ReactEvent>(&mut self) {
register_entry(
&mut self.handlers,
E::NAME,
"event",
EventRegistration {
type_id: TypeId::of::<E>(),
ts_name: <E as TS>::name,
ts_collect: |c| c.add::<E>(),
},
);
}
}