extern crate sdl2;

use sdl2::image::LoadTexture;
use sdl2::pixels::Color;
use sdl2::event::Event;
use sdl2::keyboard::Keycode;
use sdl2::ttf;
use sdl2::image;
use sdl2::rect::Rect;

const RESOURCE_DIR: &str = env!("RESOURCE_DIR");

fn main() {
    let sdl_ctx = sdl2::init().unwrap_or_else(|_| {
        eprintln!("error: could not init sdl2");
        panic!()
    });
    let video_ctx = sdl_ctx.video().unwrap_or_else(|_| {
        eprintln!("error: could not init sdl2 video subsystem");
        panic!()
    });

    let ttf_ctx = ttf::init().unwrap_or_else(|_| {
        eprintln!("error: could not init sdl2 font subsystem");
        panic!()
    });
    let fira_code_path = RESOURCE_DIR.to_owned() + "/fonts/fira-code-regular.ttf";
    let fira_code = ttf_ctx.load_font(fira_code_path, 64).unwrap_or_else(|_| {
        eprintln!("error: could not load font");
        panic!()
    });

    let _ = image::init(image::InitFlag::PNG).unwrap_or_else(|_| {
        eprintln!("error: could not init sdl2 image subsystem");
        panic!()
    });

    let window = video_ctx.window("Rust SDL2 Demo", 1000, 1000)
        .position_centered().build().unwrap_or_else(|_| {
            eprintln!("error: could not create window");
            panic!()
        });
    let mut canvas = window.into_canvas().build().unwrap_or_else(|_| {
        eprintln!("error: could not create canvas for window");
        panic!()
    });

    draw_loop(&sdl_ctx, &mut canvas, &fira_code);
}

fn draw_loop(cxt: &sdl2::Sdl, 
             canvas: &mut sdl2::render::WindowCanvas,
             font: &ttf::Font) {
    canvas.set_draw_color(Color::WHITE);
    canvas.clear();
    canvas.present();
    let texture_creator = canvas.texture_creator();
    let img_path = RESOURCE_DIR.to_owned() + "/img/ina.png";
    let img_png = texture_creator.load_texture(img_path).unwrap_or_else(|_| {
        eprintln!("error: could not load ina png");
        panic!()
    });
    let img_box = get_box_for_texture(canvas.window(), &img_png, 0.3);
    let mut event_pump = cxt.event_pump().unwrap();
    let mut color: u8 = 255;
    'game_loop: loop {
        let color1 = Color::RGB(color, color, color);
        let color2 = Color::RGB(255 - color, 255 - color, 255 - color);
        canvas.set_draw_color(color1);
        canvas.clear();
        
        canvas.set_draw_color(color2);
        let _ = canvas.fill_rect(Rect::new(100, 100, 800, 800));

        canvas.set_draw_color(color1);
        let _ = canvas.fill_rect(Rect::new(200, 200, 600, 600));

        canvas.set_draw_color(color2);
        let _ = canvas.fill_rect(Rect::new(300, 300, 400, 400));

        canvas.set_draw_color(color1);
        let _ = canvas.fill_rect(Rect::new(400, 400, 200, 200));

        canvas.set_draw_color(color2);
        let text_surround_box = get_box_for_text(canvas.window(), font, "SDL2 Rust Demo");
        let _ = canvas.fill_rect(text_surround_box);
        canvas.set_draw_color(color1);
        let _ = canvas.draw_rect(text_surround_box);
        let text_suface = font.render("SDL2 Rust Demo").solid(color1).unwrap();
        let text_texture = texture_creator.create_texture_from_surface(text_suface).unwrap();
        let _ = canvas.copy(&text_texture, None, text_surround_box);

        let _ = canvas.copy(&img_png, None, img_box);

        for evt in event_pump.poll_iter() {
            match evt {
                Event::Quit {..} |
                Event::KeyDown { keycode: Some(Keycode::Q), .. } |
                Event::KeyDown { keycode: Some(Keycode::Escape), .. } => break 'game_loop,
                Event::KeyDown { keycode: Some(Keycode::Equals), .. } => if color < 255 { color += 5 },
                Event::KeyDown { keycode: Some(Keycode::Minus), .. } => if color > 0 { color -= 5 },
                _ => {}
            }
        }
        canvas.present();
    }
}

fn get_box_for_text(win: &sdl2::video::Window, font: &ttf::Font, text: &str) -> Rect {
    let (ww, wh) = win.size();
    let (tw, th) = font.size_of(text).unwrap();
    let cx = (ww as f32 / 2.0) as i32;
    let cy = (wh as f32 / 2.0) as i32;
    Rect::new(
        cx - (tw as f32 / 2.0) as i32,
        cy - (th as f32 / 2.0) as i32,
        tw,
        th
    )
}

fn get_box_for_texture(win: &sdl2::video::Window, tex: &sdl2::render::Texture, scale: f32) -> Rect {
    let tq = tex.query();
    let tw = (tq.width as f32 * scale) as u32;
    let th = (tq.height as f32 * scale) as u32;
    let (ww, _) = win.size();
    Rect::new(
        ((ww as f32 / 2.0) - (tw as f32 / 2.0)) as i32,
        10,
        tw,
        th
    )
}
