use std::{env::var, path::Path};

enum BuildEnv {
    Meson,
    Direct,
}
struct BuildContext {
    profile: String,
    application_id: String,
    pkgdata_dir: String,
    locale_dir: String,
    gettext_package: String,
    version: String,
    config_init_code: String,
}

fn env_changed_prefix(key: &str) {
    println!("cargo::rerun-if-env-changed=PAKET_{}", key);
}

fn env_changed(key: &str) {
    println!("cargo::rerun-if-env-changed={}", key);
}

fn env_get_prefix(key: &str) -> String {
    env_get(format!("PAKET_{}", key).as_str())
}

fn env_get(key: &str) -> String {
    var(key).expect(format!("{} not found, but required by PAKET_BUILD_BY", key).as_str())
}

fn main() {
    let env = var("PAKET_BUILY_BY")
        .map_or(Some(BuildEnv::Direct), |string| {
            if string.eq_ignore_ascii_case("meson") {
                Some(BuildEnv::Meson)
            } else if string.eq_ignore_ascii_case("direct") || string.eq_ignore_ascii_case("cargo")
            {
                Some(BuildEnv::Direct)
            } else {
                None
            }
        })
        .expect("PAKET_BUILT_BY doesn't contain a valid build target");
    // shouldn't happen theortically
    env_changed_prefix("BUILT_BY");

    println!("cargo::rerun-if-changed=build.rs");

    let out_dir = std::env::var("OUT_DIR").unwrap();
    let context = match env {
        BuildEnv::Meson => {
            env_changed("PROFILE");
            env_changed_prefix("APPLICATION_ID");
            env_changed_prefix("PKGDATADIR");
            env_changed_prefix("LOCALEDIR");
            env_changed_prefix("GETTEXT_PACKAGE");
            env_changed_prefix("VERSION");

            BuildContext {
                profile: env_get("PROFILE"),
                application_id: env_get_prefix("APPLICATION_ID"),
                pkgdata_dir: env_get_prefix("PKGDATADIR"),
                locale_dir: env_get_prefix("LOCALEDIR"),
                gettext_package: env_get_prefix("GETTEXT_PACKAGE"),
                version: env_get_prefix("VERSION"),
                config_init_code: "".to_string(),
            }
        }
        BuildEnv::Direct => {
            println!("cargo::rerun-if-changed=assets");

            glib_build_tools::compile_resources(&["."], "paket.gresource.xml", "paket.gresource");

            BuildContext {
                profile: env_get("PROFILE"),
                application_id: "de.j4ne.Paket".to_string(),
                version: env_get("CARGO_PKG_VERSION"),
                pkgdata_dir: format!("{}/pkgdata", env_get("OUT_DIR")),
                locale_dir: format!("{}/locale", env_get("OUT_DIR")),
                gettext_package: "paket".to_string(),
                config_init_code: format!(
                    "gtk::gio::resources_register_include!(\"paket.gresource\").unwrap();"
                ),
            }
        }
    };

    let dest_path = Path::new(&out_dir).join("config.rs");
    std::fs::write(
        &dest_path,
        format!(
            "
pub static VERSION: &str = \"{version}\";
pub static GETTEXT_PACKAGE: &str = \"{gettext_package}\";
pub static LOCALEDIR: &str = \"{locale_dir}\";
pub static PKGDATADIR: &str = \"{pkgdata_dir}\";
pub static APPLICATION_ID: &str = \"{application_id}\";
pub static PROFILE: &str = \"{profile}\";

pub fn init() {{
        {code_init}
}}",
            version = context.version,
            gettext_package = context.gettext_package,
            locale_dir = context.locale_dir,
            pkgdata_dir = context.pkgdata_dir,
            application_id = context.application_id,
            profile = context.profile,
            code_init = context.config_init_code,
        ),
    )
    .unwrap();
}