mod gl {
    extern crate gl;
    pub use self::gl::types::*;
    pub use self::gl::*;
}
extern crate glutin;
extern crate imagefmt;
extern crate rodio;
extern crate tiled;

pub mod board;
pub mod graphics;
// pub mod audio;

use graphics as gfx;

// Shader sources
static VS_SRC: &'static str = include_str!("../shaders/basic_vertex.glsl");
static FS_SRC: &'static str = include_str!("../shaders/basic_fragment.glsl");


/// the main loop of the game, setting up and running the window and
/// event loop
pub fn main_loop() -> Result<(), gfx::Error> {
    let t = tiled::parse_file(
        std::path::Path::new("assets/maps/main.tmx")
    ).unwrap();
    let board = board::Board::from_tiled(&t);

    // let audio = audio::Audio::init()?;
    let window = gfx::Window::create()?;

    let program = gfx::Program::link(vec![
        gfx::Shader::compile(gfx::ShaderType::Vertex, VS_SRC)?,
        gfx::Shader::compile(gfx::ShaderType::Fragment, FS_SRC)?,
    ])?;

    let tex = gfx::Texture::new_from_png("assets/tiles/spritesheet.png")?;
    let nrm = gfx::Texture::new_from_png("assets/tiles/spritesheet-normal.png")?;

    let tile_data = graphics::vertices::make_grid_with(
        board::BOARD_WIDTH as usize,
        board::BOARD_HEIGHT as usize,
        &board,
    );
    let vbo = gfx::VertexBuffer::new_array_buffer(
        gfx::VertexArray::new(&program),
        &tile_data,
    );

    let upper_tile_data = graphics::vertices::make_upper_grid_with(
        board::BOARD_WIDTH as usize,
        board::BOARD_HEIGHT as usize,
        &board,
    );
    let upper_vbo = gfx::VertexBuffer::new_array_buffer(
        gfx::VertexArray::new(&program),
        &upper_tile_data,
    );

    program.use_program();
    program.bind_frag_data_location(0, "out_color")?;

    vbo.with (|r| {
        r.bind_position("position")?;
        r.bind_uv("uv")
    })?;

    upper_vbo.with( |r| {
        r.bind_position("position")?;
        r.bind_uv("uv")
    })?;

    program.set_texture("tex", &tex, 0).unwrap();
    program.set_texture("nrm", &nrm, 1).unwrap();

    window.run(|event| {
        use glutin::{ControlFlow, Event, WindowEvent, VirtualKeyCode};

        match event {
            Event::WindowEvent { event: WindowEvent::Closed, .. } =>
                return ControlFlow::Break,
            Event::WindowEvent {
                event: WindowEvent::KeyboardInput {
                    input: k,
                    ..
                },
                ..
            } if k.state == glutin::ElementState::Pressed => {
                match k.virtual_keycode {
                    Some(VirtualKeyCode::Q) =>
                        return ControlFlow::Break,
                    Some(_) => (),
                        // audio.play(format!("{:#?}", c)),
                    _ => (),
                }
            }
            _ => (),
        }

        gfx::clear();
        vbo.with(|r| r.draw());
        upper_vbo.with(|r| r.draw());

        ControlFlow::Continue
    })?;

    Ok(())
}
