use crate::tui::ecs::events::{InputEvent, Message};
use crate::tui::ecs::resources::MouseButton;
use crate::tui::ecs::world::World;
use crate::tui::key_code::KeyCode;
use crossterm::event::{self, Event, KeyEventKind, MouseEventKind};
use std::time::Duration;

fn crossterm_button_to_mouse_button(button: crossterm::event::MouseButton) -> MouseButton {
    match button {
        crossterm::event::MouseButton::Left => MouseButton::Left,
        crossterm::event::MouseButton::Right => MouseButton::Right,
        crossterm::event::MouseButton::Middle => MouseButton::Middle,
    }
}

pub fn poll_input(world: &mut World) {
    world.resources.keyboard.clear_frame();
    world.resources.mouse.clear_frame();

    while let Ok(true) = event::poll(Duration::ZERO) {
        let Ok(event) = event::read() else {
            continue;
        };

        match event {
            Event::Key(key_event) => {
                let key: KeyCode = key_event.code.into();

                match key_event.kind {
                    KeyEventKind::Press => {
                        world.resources.keyboard.pressed.insert(key);
                        world.resources.keyboard.just_pressed.insert(key);
                        world.resources.event_bus.publish(Message::Input {
                            event: InputEvent::KeyPress { key },
                        });
                    }
                    KeyEventKind::Release => {
                        world.resources.keyboard.pressed.remove(&key);
                        world.resources.keyboard.just_released.insert(key);
                        world.resources.event_bus.publish(Message::Input {
                            event: InputEvent::KeyRelease { key },
                        });
                    }
                    KeyEventKind::Repeat => {
                        world.resources.keyboard.just_pressed.insert(key);
                        world.resources.event_bus.publish(Message::Input {
                            event: InputEvent::KeyPress { key },
                        });
                    }
                }
            }
            Event::Mouse(mouse_event) => {
                let column = mouse_event.column;
                let row = mouse_event.row;

                match mouse_event.kind {
                    MouseEventKind::Down(button) => {
                        let button = crossterm_button_to_mouse_button(button);
                        world.resources.mouse.column = column;
                        world.resources.mouse.row = row;
                        match button {
                            MouseButton::Left => {
                                world.resources.mouse.left_pressed = true;
                                world.resources.mouse.left_just_pressed = true;
                            }
                            MouseButton::Right => {
                                world.resources.mouse.right_pressed = true;
                                world.resources.mouse.right_just_pressed = true;
                            }
                            MouseButton::Middle => {
                                world.resources.mouse.middle_pressed = true;
                                world.resources.mouse.middle_just_pressed = true;
                            }
                        }
                        world.resources.event_bus.publish(Message::Input {
                            event: InputEvent::MousePress {
                                button,
                                column,
                                row,
                            },
                        });
                    }
                    MouseEventKind::Up(button) => {
                        let button = crossterm_button_to_mouse_button(button);
                        world.resources.mouse.column = column;
                        world.resources.mouse.row = row;
                        match button {
                            MouseButton::Left => {
                                world.resources.mouse.left_pressed = false;
                                world.resources.mouse.left_just_released = true;
                            }
                            MouseButton::Right => {
                                world.resources.mouse.right_pressed = false;
                                world.resources.mouse.right_just_released = true;
                            }
                            MouseButton::Middle => {
                                world.resources.mouse.middle_pressed = false;
                                world.resources.mouse.middle_just_released = true;
                            }
                        }
                        world.resources.event_bus.publish(Message::Input {
                            event: InputEvent::MouseRelease {
                                button,
                                column,
                                row,
                            },
                        });
                    }
                    MouseEventKind::Moved | MouseEventKind::Drag(_) => {
                        world.resources.mouse.column = column;
                        world.resources.mouse.row = row;
                        world.resources.event_bus.publish(Message::Input {
                            event: InputEvent::MouseMove { column, row },
                        });
                    }
                    MouseEventKind::ScrollUp => {
                        world.resources.mouse.scroll_delta = 1;
                        world.resources.event_bus.publish(Message::Input {
                            event: InputEvent::MouseScroll {
                                delta: 1,
                                column,
                                row,
                            },
                        });
                    }
                    MouseEventKind::ScrollDown => {
                        world.resources.mouse.scroll_delta = -1;
                        world.resources.event_bus.publish(Message::Input {
                            event: InputEvent::MouseScroll {
                                delta: -1,
                                column,
                                row,
                            },
                        });
                    }
                    _ => {}
                }
            }
            Event::Resize(columns, rows) => {
                world.resources.terminal_size.columns = columns;
                world.resources.terminal_size.rows = rows;
                world.resources.event_bus.publish(Message::Input {
                    event: InputEvent::Resize { columns, rows },
                });
            }
            _ => {}
        }
    }
}
