use std::{
    process, thread,
    time::{Duration, Instant},
};

use sdl2::{
    event::{Event, WindowEvent},
    keyboard::Keycode,
};

use crate::{Game, InWorld, RenderAvailable, input::InputHandler};

#[derive(Debug, Default)]
pub struct Vector3 {
    pub x: f32,
    pub y: f32,
    pub z: f32,
}

#[derive(Debug, Default)]
pub struct Camera {
    pub origin: Vector3,
    pub rotation: Vector3,
}

impl Game<InWorld> {
    pub fn main_loop(mut self) -> Game<RenderAvailable> {
        println!("Starting main loop");
        let mut event_pump = self
            .state
            .sdl_context
            .event_pump()
            .expect("Failed to get event pump");
        let mouse = self.state.sdl_context.mouse();

        mouse.set_relative_mouse_mode(true);

        let mut running = true;
        while running {
            let now = Instant::now();
            for event in event_pump.poll_iter() {
                match event {
                    // Setting running to false just returns to
                    // RenderAvailable state (and then main menu)
                    Event::Quit { .. } => process::exit(0),
                    Event::Window {
                        win_event: WindowEvent::Resized(w, h),
                        ..
                    } => {
                        self.window_resize((w as u32, h as u32));
                    }
                    Event::KeyDown {
                        keycode: Some(keycode),
                        keymod,
                        repeat,
                        ..
                    } => self.handle_keydown(keycode, keymod, repeat),

                    Event::KeyUp {
                        keycode: Some(keycode),
                        keymod,
                        repeat,
                        ..
                    } => self.handle_keyup(keycode, keymod, repeat),
                    Event::MouseMotion {
                        mousestate,
                        x,
                        y,
                        xrel,
                        yrel,
                        ..
                    } => self.handle_mouse_motion(mousestate, (x, y), (xrel, yrel)),
                    _ => {}
                }
            }
            event_pump
                .keyboard_state()
                .pressed_scancodes()
                .filter_map(Keycode::from_scancode)
                .for_each(|k| self.handle_cont_key(k));

            self.render_frame();

            let elapsed = now.elapsed();
            let delay = (1_000_000u128 / 60).saturating_sub(elapsed.as_micros());
            thread::sleep(Duration::from_micros(delay as u64));
        }

        Game {
            state: RenderAvailable {
                sdl_context: self.state.sdl_context,
                window: self.state.window,
                ctx: self.state.ctx,
            },
        }
    }
}
