use clap::Parser;
use earthbound_battle_backgrounds::{
    Emulator, Layers, MAX_LAYER, Options, SNES_HEIGHT, SNES_WIDTH,
};
use log::*;
use pixels::{Error, Pixels, SurfaceTexture};
use winit::dpi::LogicalSize;
use winit::event::{Event, WindowEvent};
use winit::event_loop::EventLoop;
use winit::keyboard::KeyCode;
use winit::window::WindowBuilder;
use winit_input_helper::WinitInputHelper;

#[derive(Parser)]
struct Cli {
    /// Layer 1 style.
    #[arg(long, value_parser = clap::value_parser!(u16).range(..i64::from(MAX_LAYER)))]
    layer1: u16,

    /// Layer 2 style.
    #[arg(long, value_parser = clap::value_parser!(u16).range(..i64::from(MAX_LAYER)))]
    layer2: u16,
}

fn main() -> Result<(), Error> {
    let cli = Cli::parse();

    let event_loop = EventLoop::new().unwrap();
    let mut input = WinitInputHelper::new();
    let window = {
        let size = LogicalSize::new(SNES_WIDTH, SNES_HEIGHT);
        WindowBuilder::new()
            .with_title("EarthBound Battle Backgrounds")
            .with_inner_size(size)
            .with_min_inner_size(size)
            .build(&event_loop)
            .unwrap()
    };

    let mut pixels = {
        let window_size = window.inner_size();
        let surface_texture = SurfaceTexture::new(window_size.width, window_size.height, &window);
        Pixels::new(SNES_WIDTH.into(), SNES_HEIGHT.into(), surface_texture)?
    };

    let mut emulator = Emulator::new(Options {
        layers: Layers::new(cli.layer1, cli.layer2),
        ..Default::default()
    });

    let res = event_loop.run(|event, elwt| {
        if let Event::WindowEvent {
            event: WindowEvent::RedrawRequested,
            ..
        } = event
        {
            emulator.draw_frame(pixels.frame_mut());
            if let Err(err) = pixels.render() {
                error!("render: {}", err);
                elwt.exit();
                return;
            }
        }

        if input.update(&event) {
            if input.key_pressed(KeyCode::Escape) || input.close_requested() {
                elwt.exit();
                return;
            }

            if let Some(size) = input.window_resized() {
                if let Err(err) = pixels.resize_surface(size.width, size.height) {
                    error!("resize surface: {}", err);
                    elwt.exit();
                    return;
                }
            }

            window.request_redraw();
        }
    });
    res.map_err(|e| Error::UserDefined(Box::new(e)))
}
