use std::fs::OpenOptions;
use std::io::{Read, Seek, SeekFrom, Write};
use std::path::Path;

fn main() {
    let out_path = Path::new("./src/bindings.rs");
    let file = OpenOptions::new().write(true).create(true).open(&out_path);

    match file {
        Err(error) => {
            println!("cargo:warning={error}");
        }

        Ok(_) => {
            let disasm_dir = Path::new("disasm");

            let bindings = bindgen::Builder::default()
                .header(disasm_dir.join("ghidra.h").to_str().unwrap())
                .header(disasm_dir.join("mw4_funcs.h").to_str().unwrap())
                .header(disasm_dir.join("mw4_globals.h").to_str().unwrap())
                .header(disasm_dir.join("mw4_types.h").to_str().unwrap())
                .clang_arg(format!("-I{}", disasm_dir.to_str().unwrap()))
                .generate();

            match bindings {
                Err(error) => {
                    println!("cargo:warning={error}");
                }

                Ok(bindings) => {
                    bindings.write_to_file(out_path).expect(
                        format!("Couldn't write to {}", out_path.to_str().unwrap()).as_str(),
                    );

                    prepend_to_file(
                        out_path.to_str().unwrap(),
                        "#![allow(non_snake_case, non_camel_case_types, non_upper_case_globals)]\n",
                    )
                    .expect("Couldn't append to the start of file.");
                }
            }

            cc::Build::new()
                .file(disasm_dir.join("mw4_funcs.c").to_str().unwrap())
                .include(disasm_dir)
                .compile("disasm");
        }
    }
}

fn prepend_to_file(filename: &str, content: &str) -> std::io::Result<()> {
    let mut file = OpenOptions::new()
        .read(true)
        .write(true)
        .create(true)
        .open(filename)?;

    let mut old_content = Vec::new();
    file.read_to_end(&mut old_content)?;

    file.seek(SeekFrom::Start(0))?;
    file.write_all(content.as_bytes())?;
    file.write_all(&old_content)?;

    Ok(())
}
