use sdl2::{
    keyboard::{Keycode, Mod},
    mouse::MouseState,
};

use crate::{Game, InWorld};

use super::InputHandler;

const MOV_STEP: f32 = 0.05;
const ROT_MOUSE_SCALE: f32 = 0.001;

impl InputHandler for Game<InWorld> {
    fn handle_cont_key(&mut self, keycode: Keycode) {
        let Self {
            state: InWorld { camera, .. },
        } = self;

        match keycode {
            Keycode::W => {
                camera.origin.x -= -camera.rotation.y.sin() * MOV_STEP;
                camera.origin.z -= camera.rotation.y.cos() * MOV_STEP;
            }
            Keycode::S => {
                camera.origin.x += -camera.rotation.y.sin() * MOV_STEP;
                camera.origin.z += camera.rotation.y.cos() * MOV_STEP;
            }
            Keycode::A => {
                camera.origin.x += camera.rotation.y.cos() * MOV_STEP;
                camera.origin.z += camera.rotation.y.sin() * MOV_STEP;
            }
            Keycode::D => {
                camera.origin.z -= camera.rotation.y.sin() * MOV_STEP;
                camera.origin.x -= camera.rotation.y.cos() * MOV_STEP;
            }
            Keycode::Space => {
                camera.origin.y += MOV_STEP;
            }
            Keycode::LShift => {
                camera.origin.y -= MOV_STEP;
            }
            _ => {}
        }
    }

    fn handle_keydown(&mut self, keycode: Keycode, modifier: Mod, repeat: bool) {
        match keycode {
            Keycode::Escape => {
                let mouse = self.state.sdl_context.mouse();
                mouse.set_relative_mouse_mode(!mouse.relative_mouse_mode());
            }
            _ => {}
        }
    }

    fn handle_mouse_motion(
        &mut self,
        state: MouseState,
        abs: (i32, i32),
        (xrel, yrel): (i32, i32),
    ) {
        if self.state.sdl_context.mouse().relative_mouse_mode() {
            self.state.camera.rotation.y -= xrel as f32 * ROT_MOUSE_SCALE;
            self.state.camera.rotation.x -= yrel as f32 * ROT_MOUSE_SCALE;
        }
    }
}
