use crate::tui::ecs::resources::MouseButton;
use crate::tui::key_code::KeyCode;
use std::any::Any;
use std::collections::VecDeque;

#[derive(Debug, Clone)]
pub enum InputEvent {
    KeyPress {
        key: KeyCode,
    },
    KeyRelease {
        key: KeyCode,
    },
    Resize {
        columns: u16,
        rows: u16,
    },
    MousePress {
        button: MouseButton,
        column: u16,
        row: u16,
    },
    MouseRelease {
        button: MouseButton,
        column: u16,
        row: u16,
    },
    MouseMove {
        column: u16,
        row: u16,
    },
    MouseScroll {
        delta: i16,
        column: u16,
        row: u16,
    },
}

pub enum Message {
    Input {
        event: InputEvent,
    },
    App {
        type_name: &'static str,
        payload: Box<dyn Any + Send + Sync>,
    },
}

#[derive(Default)]
pub struct EventBus {
    pub messages: VecDeque<Message>,
}

impl EventBus {
    pub fn publish(&mut self, message: Message) {
        self.messages.push_back(message);
    }

    pub fn publish_input(&mut self, event: InputEvent) {
        self.messages.push_back(Message::Input { event });
    }

    pub fn publish_app_event<T: Any + Send + Sync + 'static>(&mut self, event: T) {
        self.messages.push_back(Message::App {
            type_name: std::any::type_name::<T>(),
            payload: Box::new(event),
        });
    }
}
