use std::fs::File;
use std::io::{stderr, Write};
use std::process::{Command, Output};
use std::path::Path;
use std::env;

fn run_cmd(command: &mut Command) -> Output {
    let stream = stderr();
    let mut f = stream.lock();
    let res = command.output();
    match res {
        Ok(output) => if !output.status.success() {
            write!(&mut f, "Command `{:?}` failed", command).unwrap();
            panic!("{}", String::from_utf8_lossy(&output.stderr[..]))
        } else {
            output
        },
        Err(err) => {
            write!(&mut f, "Command `{:?}` failed", command).unwrap();
            panic!("{}", err)
        }
    }
}

fn main()
{
    let source_file = Path::new("src/codegen/type_size.c");
    if !source_file.exists() {
        panic!("Could not find file: {}", source_file.to_string_lossy());
    }

    let out_dir_var = match env::var("OUT_DIR") {
        Ok(dir) => dir,
        Err(e) => panic!("Could not get env value OUT_DIR: {}", e)
    };
    let out_dir = Path::new(&out_dir_var);
    if !out_dir.exists() {
        panic!("Could not find directory: {}", out_dir.to_string_lossy());
    }

    let out_file = out_dir.join("codegen");

    let mut gcc_cmd = Command::new("gcc");
    gcc_cmd.arg(source_file)
        .arg("-o").arg(&out_file);

    match env::var("LIBYAML_CFLAGS") {
        Ok(compile_flags) => { gcc_cmd.arg(&compile_flags); },
        Err(_) => ()
    }

    run_cmd(&mut gcc_cmd);

    let mut codegen_cmd = Command::new(&out_file);
    let output = run_cmd(&mut codegen_cmd);

    let generated_file = out_dir.join("type_size.rs");
    let mut f = match File::create(generated_file) {
        Ok(f) => f,
        Err(e) => panic!("Could not open file $OUT_DIR/type_size.rs: {}", e)
    };

    match f.write_all(&output.stdout[..]) {
        Err(e) => panic!("Could not write to $OUT_DIR/type_size.rs: {}", e),
        Ok(_) => ()
    }
}
