use std::time::Duration;
use std::{any::Any, any::TypeId, fmt::Debug, sync::Arc};
use std::thread;
use crossterm::{cursor, event, execute, terminal};
use downcast_trait::downcast_trait;
use downcast_trait::DowncastTrait;
use parking_lot::RwLock;
use std::mem;
use crate::{
event::{Event, Listener},
node::HasListener,
utils::NodeRef,
};
use super::{
message::{Content, Message, Participant, RawEvent, Sender},
ICmdWindow,
};
pub struct GeneralListener {
pub func: Box<dyn Fn(NodeRef, RawEvent) -> bool + Send + Sync>,
}
impl Debug for GeneralListener {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("GeneralListener").finish()
}
}
impl<E, T> From<T> for GeneralListener
where
E: Event,
T: Listener<EventType = E> + Send + Sync + 'static,
<E as TryFrom<RawEvent>>::Error: Debug,
{
fn from(value: T) -> Self {
let value = Arc::new(RwLock::new(value));
GeneralListener {
func: Box::new(move |node, raw| {
if let Ok(e) = TryFrom::<RawEvent>::try_from(raw) {
value.write().on_event(node, e)
} else {
true
}
}),
}
}
}
#[derive(Debug)]
pub struct Interactor {
window: Arc<RwLock<ICmdWindow>>,
}
impl Interactor {
pub fn new(window: Arc<RwLock<ICmdWindow>>) -> Self {
Interactor { window }
}
pub fn launch(&self) {
while let Ok(event) = event::read() {
(match event {
event::Event::Key(key) => {
if key.code == event::KeyCode::Char('c')
&& key.modifiers == event::KeyModifiers::CONTROL
{
let stdout = &self.window.read().stdout;
let mut stdout_ = stdout.lock();
execute!(
stdout_,
cursor::MoveTo(0, 0),
terminal::Clear(terminal::ClearType::All)
)
.unwrap();
break;
} else {
Some(Message {
from: TypeId::of::<Self>(),
to: TypeId::of::<Dispatcher>(),
content: Content::Event(RawEvent::Key(key.code, key.modifiers)),
})
}
}
event::Event::Mouse(me) => Some(Message {
from: TypeId::of::<Self>(),
to: TypeId::of::<Dispatcher>(),
content: Content::Event(RawEvent::Mouse(me.column, me.row, me.kind)),
}),
_ => None,
})
.map(|msg| self.send(msg));
}
}
}
impl Sender for Interactor {
fn get_window(&self) -> Arc<RwLock<ICmdWindow>> {
self.window.clone()
}
}
#[derive(Debug)]
pub struct Dispatcher {
window: Arc<RwLock<ICmdWindow>>,
}
impl Dispatcher {
pub fn new(window: Arc<RwLock<ICmdWindow>>) -> Self {
Dispatcher { window }
}
pub fn launch(&self, root: NodeRef) {
loop {
if !Participant::update(self, root.clone()) {
thread::sleep(Duration::from_millis(1));
break;
}
}
}
}
impl Sender for Dispatcher {
fn get_window(&self) -> Arc<RwLock<ICmdWindow>> {
self.window.clone()
}
}
impl Participant for Dispatcher {
type Params = NodeRef;
fn resolve(&self, msg: Message, root: Self::Params) -> bool {
fn dispatch(root: NodeRef, event: RawEvent) {
if let Some(node) = downcast_trait!(dyn HasListener, root.as_ref().to_downcast_trait())
{
node.get_listeners().read().iter().for_each(|listener| {
(listener.func)(root.clone(), event.clone());
});
node.children().read().iter().for_each(|child| {
dispatch(child.clone(), event.clone());
});
};
}
match msg.content {
Content::Event(event) => {
dispatch(root, event);
true
}
Content::Quit => false,
_ => true,
}
}
}