//   ▄████████▄      +        ███ +  ▄█████████ ███     +
//  ███▀    ▀███ +         +  ███    ███▀  +    ███ +       +
//  ███  +   ███ ███   ███ █████████ ███        ███  ███   ███
//  ███     +███ ███   ███    ███    ███▐██████ ███  ███   ███
//  ███ +    ███ ███+  ███   +███    ███     +  ███  ███ + ███
//  ███▄    ▄███ ███▄  ███    ███ +  ███  +     ███  ███▄  ███
//   ▀████████▀ + ▀███████    ███▄   ███▄       ▀████ ▀███████
//       +                  +                +             ███
//  +   ▀████████████████████████████████████████████████████▀

use blend::Blend;
use std::fs;
use std::fs::File;
use std::io::Write;

fn main() -> std::io::Result<()> {
    let target = std::env::var("TARGET").unwrap();
    if target.contains("windows") {
        println!("cargo:warning=Embedding Windows Icon");
        embed_resource::compile("build/windows/icon.rc");
    }

    let file = File::create("src/data/scenes.in");
    if let Ok(mut file) = file {
        write!(&file, "// THIS FILE IS AUTOGENERATED BY build.rs BASED ON DATA IN src/blender/scene_*.blend FILES!\n")?;
        write!(
            &file,
            "// DO NOT MODIFY MANUALLY, CHANGES WILL BE OVERWRITTEN!\n"
        )?;
        write!(&file, "[\n")?;

        // find all scene_*.blend files and extract+export their scenes
        for entry in fs::read_dir("src/blender")? {
            let path = entry?.path();
            if let Some(file_name) = path.file_name().and_then(|s| s.to_str()) {
                if file_name.starts_with("scene_") && file_name.ends_with(".blend") {
                    let scene_name = &file_name["scene_".len()..file_name.len() - ".blend".len()];

                    extract_scene(&mut file, scene_name, path.to_str().unwrap())?;
                }
            }
        }
        write!(&file, "]\n")?;
    }
    Ok(())
}

fn extract_scene(file: &mut File, scene_name: &str, blend_file: &str) -> std::io::Result<()> {
    // Info about .blender file format:
    // https://www.janwalter.org/jekyll/blender/rust/blendinfo/2019/05/28/blend_info.html
    let blend = Blend::from_path(blend_file).expect("error loading blend file");
    for obj in blend.instances_with_code(*b"OB") {
        let loc: Vec<f32> = if obj.is_valid("loc") {
            obj.get_f32_vec("loc")
        } else {
            vec![0.0, 0.0, 0.0]
        };
        let rot: Vec<f32> = if obj.is_valid("rot") {
            obj.get_f32_vec("rot")
        } else {
            vec![0.0, 0.0, 0.0]
        };
        let scale: Vec<f32> = if obj.is_valid("size") {
            obj.get_f32_vec("size")
        } else {
            vec![1.0, 1.0, 1.0]
        };
        let name = obj.get("id").get_string("name");
        if let Some(name) = get_scene_object_name(name.as_str()) {
            write!(
                file,
                "({scene_name:?}, {name:?}, {loc:?}, {rot:?}, {scale:?}),\n"
            )?;
        }
    }
    Ok(())
}

fn get_scene_object_name(full_id: &str) -> Option<&str> {
    let prefix = "OBLOAD=";
    if full_id.starts_with(prefix) {
        let remainder: &str = &full_id[prefix.len()..];
        let parts: Vec<&str> = remainder.split('.').collect();
        let name = parts[0];
        return Some(name);
    }
    return None;
}