use crate::inventory::items::{ConsumableC, ApplianceC};
use crate::body::BodyPart;
use std::sync::{Arc, Weak};
use std::cell::{RefCell, RefMut};
use std::collections::BTreeMap;
use std::fmt;
pub(crate) trait MessageQueue {
fn has_messages(&self) -> bool;
fn queue_message(&self, message: Event);
fn get_message_queue(&self) -> RefMut<'_, BTreeMap<usize, Event>>;
}
#[derive(Clone, Debug)]
pub enum Event {
SleepStarted(f32),
WokeUp,
StaminaDrained,
OxygenDrained,
BloodDrained,
FoodDrained,
WaterDrained,
Tired,
Exhausted,
MedicalAgentActivated(String),
MedicalAgentDeactivated(String),
MedicalAgentDoseReceived(String, String),
BodyApplianceOn(String, BodyPart),
BodyApplianceOff(String, BodyPart),
ClothesOn(String),
ClothesOff(String),
DeathFromDisease(String),
DeathFromInjury(String, BodyPart),
DiseaseSpawned(String),
DiseaseRemoved(String),
DiseaseSelfHealStarted(String),
DiseaseInverted(String),
DiseaseResumed(String),
DiseaseExpired(String),
InjurySpawned(String, BodyPart),
InjuryRemoved(String, BodyPart),
InjurySelfHealStarted(String, BodyPart),
InjuryInverted(String, BodyPart),
InjuryResumed(String, BodyPart),
InjuryExpired(String, BodyPart),
BloodLossStopped(String, BodyPart),
BloodLossResumed(String, BodyPart),
ItemConsumed(ConsumableC),
ApplianceTaken(ApplianceC, BodyPart),
InventoryItemAdded(String),
InventoryItemRemoved(String),
CraftingCombinationExecuted(String),
InventoryWeightChanged(f32, f32),
InventoryItemUsedAll(String, usize),
InventoryItemUsedPartially(String, usize),
HighBloodPressureDanger,
LowBloodPressureDanger,
HighHeartRateDanger,
LowHeartRateDanger,
HighBodyTemperatureDanger,
LowBodyTemperatureDanger,
DeclaredDead
}
impl fmt::Display for Event {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{:?}", self)
}
}
pub trait Listener {
fn notify(&mut self, event: &Event);
}
pub trait Dispatchable<T>
where T: Listener
{
fn register_listener(&mut self, listener: Arc<RefCell<T>>);
}
pub struct Dispatcher<T>
where T: Listener
{
listeners: Vec<Weak<RefCell<T>>>
}
impl<T> Dispatchable<T> for Dispatcher<T>
where T: Listener
{
fn register_listener(&mut self, listener: Arc<RefCell<T>>) {
self.listeners.push(Arc::downgrade(&listener));
}
}
impl<T> Dispatcher<T>
where T: Listener
{
pub fn new() -> Dispatcher<T> {
Dispatcher { listeners: Vec::new() }
}
pub fn num_listeners(&self) -> usize {
self.listeners.len()
}
pub fn dispatch(&mut self, event: Event) {
let mut cleanup = false;
for l in self.listeners.iter() {
if let Some(listener_rc) = l.upgrade() {
let mut listener = listener_rc.borrow_mut();
listener.notify(&event);
} else {
println!("Cannot get listener, cleanup necessary");
cleanup = true;
}
}
if cleanup {
println!("Dispatcher is cleaning up weak refs");
self.listeners.retain(|ref l| {
let got_ref = l.clone().upgrade();
match got_ref {
None => false,
_ => true,
}
});
}
}
}