use std::{
any::{Any, TypeId},
collections::{BTreeMap, HashMap},
marker::PhantomData,
sync::{mpsc, Arc, Mutex},
};
use crate::shell::WindowRequest;
use dces::entity::Entity;
#[derive(Debug)]
pub struct MessageBox {
message: Box<dyn Any + Send>,
message_type: TypeId,
target: Entity,
}
impl MessageBox {
pub fn downcast<M: Any>(self) -> Result<M, String> {
if self.message_type == TypeId::of::<M>() {
return Ok(*self.message.downcast::<M>().unwrap());
}
Err("Wrong message type".to_string())
}
pub fn downcast_ref<M: Any>(&self) -> Result<&M, String> {
if self.message_type == TypeId::of::<M>() {
return Ok(&*self.message.downcast_ref::<M>().unwrap());
}
Err("Wrong message type".to_string())
}
pub fn is_type<M: Any>(&self) -> bool {
self.message_type == TypeId::of::<M>()
}
pub fn new<M>(message: M, target: Entity) -> Self
where
M: Any + Send,
{
MessageBox {
message: Box::new(message),
target,
message_type: TypeId::of::<M>(),
}
}
pub fn message_type(&self) -> TypeId {
self.message_type
}
pub fn target(&self) -> Entity {
self.target
}
}
#[derive(Clone, Debug)]
pub struct MessageAdapter {
messages: Arc<Mutex<BTreeMap<Entity, HashMap<TypeId, Vec<MessageBox>>>>>,
window_sender: mpsc::Sender<WindowRequest>,
}
impl MessageAdapter {
pub fn new(window_sender: mpsc::Sender<WindowRequest>) -> Self {
MessageAdapter {
messages: Arc::new(Mutex::new(BTreeMap::new())),
window_sender,
}
}
pub fn send_message<M: Any + Send>(&self, message: M, target: Entity) {
let mut locked_messages = self
.messages
.lock()
.expect("MessageAdapter::send_message: Cannot lock messages.");
locked_messages
.entry(target)
.or_insert_with(HashMap::new)
.entry(TypeId::of::<M>())
.or_insert_with(Vec::new)
.push(MessageBox::new(message, target));
self.window_sender
.send(WindowRequest::Redraw)
.expect("MessageAdapter::send_message: Cannot send redraw request.");
}
pub(crate) fn entities(&self) -> Vec<Entity> {
self.messages
.lock()
.expect("MessageAdapter::entities: Cannot lock messages.")
.keys()
.cloned()
.collect()
}
pub(crate) fn remove_message_for_entity(&self, target: Entity) {
self.messages
.lock()
.expect("MessageAdapter::remove_message_for_entity: Cannot lock messages.")
.remove(&target);
}
pub fn len(&self) -> usize {
self.messages
.lock()
.expect("MessageAdapter::len: Cannot lock messages.")
.len()
}
pub fn is_empty(&self) -> bool {
self.messages
.lock()
.expect("MessageAdapter::is_empty: Cannot lock messages.")
.is_empty()
}
pub(crate) fn message_reader(&self, entity: Entity) -> MessageReader {
let messages = if let Some(messages) = self
.messages
.lock()
.expect("MessageAdapter::message_reader: Cannot lock messages.")
.remove(&entity)
{
messages
} else {
HashMap::new()
};
MessageReader::new(messages, entity)
}
}
pub struct MessageReader {
messages: HashMap<TypeId, Vec<MessageBox>>,
target: Entity,
}
impl MessageReader {
pub fn new(messages: HashMap<TypeId, Vec<MessageBox>>, target: Entity) -> Self {
MessageReader { messages, target }
}
pub fn entity(&self) -> Entity {
self.target
}
pub fn contains_type<M: Any>(&self) -> bool {
self.messages.contains_key(&TypeId::of::<M>())
}
pub fn is_empty(&self) -> bool {
self.messages.is_empty()
}
pub fn read<M: Any + Send>(&mut self) -> MessageIterator<M> {
let messages = if let Some(messages) = self.messages.remove(&TypeId::of::<M>()) {
messages
} else {
vec![]
};
MessageIterator::new(messages)
}
}
#[derive(Debug)]
pub struct MessageIterator<M>
where
M: Any + Send,
{
messages: Vec<MessageBox>,
_phantom: PhantomData<M>,
}
impl<M> MessageIterator<M>
where
M: Any + Send,
{
pub(crate) fn new(messages: Vec<MessageBox>) -> Self {
MessageIterator {
messages,
_phantom: PhantomData::default(),
}
}
}
impl<M> Iterator for MessageIterator<M>
where
M: Any + Send,
{
type Item = M;
fn next(&mut self) -> Option<Self::Item> {
if self.messages.is_empty() {
return None;
}
Some(self.messages.remove(0).downcast::<M>().unwrap())
}
}