use glam::Vec2;
use sdl3::{event::Event, keyboard::Keycode};

pub struct InputState
{
    pub w: bool,
    pub a: bool,
    pub s: bool,
    pub d: bool,
    pub space: bool,
    pub shift: bool,
    pub lctrl: bool,

    pub space_just_pressed: bool,
    pub debug_cycle_just_pressed: bool,
    pub i_just_pressed: bool,
    pub j_just_pressed: bool,
    pub l_just_pressed: bool,
    pub roll_just_pressed: bool,
    pub f2_just_pressed: bool,

    pub mouse_delta: (f32, f32),
    pub mouse_captured: bool,
    pub quit_requested: bool,
}

impl InputState
{
    pub fn new() -> Self
    {
        Self {
            w: false,
            a: false,
            s: false,
            d: false,
            space: false,
            shift: false,
            lctrl: false,
            space_just_pressed: false,
            debug_cycle_just_pressed: false,
            i_just_pressed: false,
            j_just_pressed: false,
            l_just_pressed: false,
            roll_just_pressed: false,
            f2_just_pressed: false,
            mouse_delta: (0.0, 0.0),
            mouse_captured: true,
            quit_requested: false,
        }
    }

    pub fn handle_event(&mut self, event: &Event) -> bool
    {
        match event
        {
            Event::Quit { .. } =>
            {
                self.quit_requested = true;
                return true;
            }

            Event::KeyDown {
                keycode: Some(key),
                repeat,
                ..
            } =>
            {
                if !repeat
                {
                    self.handle_keydown(*key);

                    if *key == Keycode::Escape
                    {
                        self.quit_requested = true;
                        return true;
                    }
                }
            }

            Event::KeyUp {
                keycode: Some(key), ..
            } =>
            {
                self.handle_keyup(*key);
            }

            Event::MouseMotion { xrel, yrel, .. } =>
            {
                self.handle_mouse_motion(*xrel as f32, *yrel as f32);
            }

            _ =>
            {}
        }

        false
    }

    pub fn handle_keydown(&mut self, key: Keycode)
    {
        match key
        {
            Keycode::W => self.w = true,
            Keycode::A => self.a = true,
            Keycode::S => self.s = true,
            Keycode::D => self.d = true,
            Keycode::Space =>
            {
                if !self.space
                {
                    self.space_just_pressed = true;
                }
                self.space = true;
            }
            Keycode::LShift | Keycode::RShift => self.shift = true,
            Keycode::LCtrl =>
            {
                if !self.lctrl
                {
                    self.roll_just_pressed = true;
                }
                self.lctrl = true;
            }
            Keycode::I => self.i_just_pressed = true,
            Keycode::J => self.j_just_pressed = true,
            Keycode::L => self.l_just_pressed = true,
            Keycode::F1 => self.debug_cycle_just_pressed = true,
            Keycode::F2 => self.f2_just_pressed = true,
            _ =>
            {}
        }
    }

    pub fn handle_keyup(&mut self, key: Keycode)
    {
        match key
        {
            Keycode::W => self.w = false,
            Keycode::A => self.a = false,
            Keycode::S => self.s = false,
            Keycode::D => self.d = false,
            Keycode::Space => self.space = false,
            Keycode::LShift | Keycode::RShift => self.shift = false,
            Keycode::LCtrl => self.lctrl = false,
            _ =>
            {}
        }
    }

    pub fn handle_mouse_motion(&mut self, xrel: f32, yrel: f32)
    {
        if self.mouse_captured
        {
            self.mouse_delta = (xrel, yrel);
        }
    }

    pub fn clear_just_pressed(&mut self)
    {
        self.space_just_pressed = false;
        self.debug_cycle_just_pressed = false;
        self.i_just_pressed = false;
        self.j_just_pressed = false;
        self.l_just_pressed = false;
        self.roll_just_pressed = false;
        self.f2_just_pressed = false;
        self.mouse_delta = (0.0, 0.0);
    }

    pub fn get_movement_input(&self) -> Vec2
    {
        let mut input = Vec2::ZERO;

        if self.w
        {
            input.y += 1.0;
        }
        if self.s
        {
            input.y -= 1.0;
        }
        if self.a
        {
            input.x -= 1.0;
        }
        if self.d
        {
            input.x += 1.0;
        }

        if input.length_squared() > 1.0
        {
            input = input.normalize();
        }

        input
    }
}
