use std::{env, path::PathBuf, process::Command};

fn search_pat(base: &str, pat: &str) -> bool {
    let res = Command::new("find")
        .arg(base)
        .arg("-name")
        .arg(pat)
        .output();
    match dbg!(res) {
        Err(_) => false,
        Ok(output) => output.stdout.len() > 0,
    }
}

enum Gssapi {
    Mit,
    Heimdal,
    Apple,
}

fn which() -> Gssapi {
    if cfg!(target_os = "macos") {
        return Gssapi::Apple;
    } else if cfg!(target_os = "windows") {
        panic!("use SSPI on windows")
    } else if cfg!(target_family = "unix") {
        let ldpath = env::var("LD_LIBRARY_PATH").unwrap();
        let paths = vec!["/lib", "/lib64", "/usr/lib", "/usr/lib64"];
        for path in ldpath.split(':').chain(paths) {
            if search_pat(path, "libgssapi_krb5.so*") {
                return Gssapi::Mit;
            }
            if search_pat(path, "libgssapi.so*") {
                return Gssapi::Heimdal;
            }
        }
        panic!("no gssapi implementation found, install mit kerberos or heimdal");
    } else {
        panic!("libgssapi isn't ported to this platform yet")
    }
}

fn main() {
    let imp = which();
    match imp {
        Gssapi::Mit => println!("cargo:rustc-link-lib=gssapi_krb5"),
        Gssapi::Heimdal => println!("cargo:rustc-link-lib=gssapi"),
        Gssapi::Apple => println!("cargo:rustc-link-lib=framework=GSS"),
    }
    let builder = bindgen::Builder::default();
    let builder = match imp {
        Gssapi::Mit | Gssapi::Heimdal => builder,
        Gssapi::Apple =>
            builder.clang_arg("-F/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks")
    };
    let bindings = builder
        .whitelist_type("(OM_.+|gss_.+)")
        .whitelist_var("_?GSS_.+|gss_.+")
        .whitelist_function("gss_.*|__ApplePrivate.*")
        .header(match imp {
            Gssapi::Mit => "src/wrapper_mit.h",
            Gssapi::Heimdal => "src/wrapper_heimdal.h",
            Gssapi::Apple => "src/wrapper_apple.h",
        })
        .generate()
        .expect("failed to generate gssapi bindings");
    let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
    bindings
        .write_to_file(out_path.join("bindings.rs"))
        .expect("failed to write bindings")
}
