use crate::ecs::event_bus::commands::publish_event;
use crate::ecs::world::{Vec2, World, events::*, resources::MouseState};
use winit::event::WindowEvent;

pub fn receive_keyboard_input(world: &mut World, event: &WindowEvent) {
    let WindowEvent::KeyboardInput {
        event:
            winit::event::KeyEvent {
                physical_key: winit::keyboard::PhysicalKey::Code(key_code),
                state,
                ..
            },
        ..
    } = event
    else {
        return;
    };
    *world
        .resources
        .input
        .keyboard
        .keystates
        .entry(*key_code)
        .or_insert(*state) = *state;

    let event_state = match state {
        winit::event::ElementState::Pressed => InputEvent::KeyboardInput {
            key_code: *key_code as u32,
            state: crate::ecs::world::events::KeyState::Pressed,
        },
        winit::event::ElementState::Released => InputEvent::KeyboardInput {
            key_code: *key_code as u32,
            state: crate::ecs::world::events::KeyState::Released,
        },
    };

    publish_event(world, Message::Input { event: event_state });
}

pub fn receive_mouse_input(world: &mut World, event: &WindowEvent) {
    let mouse = &mut world.resources.input.mouse;
    match event {
        WindowEvent::MouseInput { button, state, .. } => {
            let clicked = *state == winit::event::ElementState::Pressed;
            match button {
                winit::event::MouseButton::Left => {
                    mouse.state.set(MouseState::LEFT_CLICKED, clicked);
                }
                winit::event::MouseButton::Middle => {
                    mouse.state.set(MouseState::MIDDLE_CLICKED, clicked);
                }
                winit::event::MouseButton::Right => {
                    mouse.state.set(MouseState::RIGHT_CLICKED, clicked);
                }
                _ => {}
            }
        }
        WindowEvent::CursorMoved { position, .. } => {
            let last_position = mouse.position;
            let current_position = Vec2::new(position.x as _, position.y as _);
            mouse.position = current_position;
            mouse.position_delta = current_position - last_position;
            mouse.state.set(MouseState::MOVED, true);
        }
        WindowEvent::MouseWheel {
            delta: winit::event::MouseScrollDelta::LineDelta(h_lines, v_lines),
            ..
        } => {
            mouse.wheel_delta = Vec2::new(*h_lines, *v_lines);
            mouse.state.set(MouseState::SCROLLED, true);
        }
        _ => {}
    }
}
