use crate::core::entity::{EntityId, EntityMap};
use std::any::Any;
use std::collections::{HashMap, VecDeque};
use std::rc::Rc;
pub(crate) type Listener = Rc<dyn Fn(&mut EntityMap, &dyn Any)>;
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct Subscription(u64);
#[derive(Default)]
pub(crate) struct EventQueue {
pending: VecDeque<(EntityId, Box<dyn Any>)>,
listeners: HashMap<EntityId, Vec<(Subscription, EntityId, Listener)>>,
next_id: u64,
}
impl EventQueue {
pub fn push(&mut self, emitter: EntityId, event: Box<dyn Any>) {
self.pending.push_back((emitter, event));
}
pub fn pop(&mut self) -> Option<(EntityId, Box<dyn Any>)> {
self.pending.pop_front()
}
pub fn subscribe(
&mut self,
emitter: EntityId,
subscriber: EntityId,
listener: impl Fn(&mut EntityMap, &dyn Any) + 'static,
) -> Subscription {
self.next_id += 1;
let subscription = Subscription(self.next_id);
self.listeners.entry(emitter).or_default().push((subscription, subscriber, Rc::new(listener)));
subscription
}
pub fn unsubscribe(&mut self, subscription: Subscription) {
for listeners in self.listeners.values_mut() {
listeners.retain(|(id, _, _)| *id != subscription);
}
}
pub fn listeners(&self, emitter: EntityId) -> Vec<Listener> {
self.listeners
.get(&emitter)
.map(|listeners| listeners.iter().map(|(_, _, listener)| listener.clone()).collect())
.unwrap_or_default()
}
pub fn forget(&mut self, id: EntityId) {
self.listeners.remove(&id);
for listeners in self.listeners.values_mut() {
listeners.retain(|(_, subscriber, _)| *subscriber != id);
}
}
}