#[macro_use]
extern crate bindgen;
extern crate cc;
extern crate cfg_if;

// use std::env;
// use std::path::PathBuf;

// #[cfg(all(feature = "royal_poker", feature = "standard_poker"))]
// compile_error!("one feature should be choosed");

// #[cfg(not(any(feature = "royal_poker", feature = "standard_poker", feature = "numeral_poker")))]
// compile_error!("one feature should be choosed");


cfg_if::cfg_if! {
    if #[cfg(all(feature = "royal_poker", not(feature = "standard_poker"), not(feature = "numeral_poker"), not(features = "rust_waugh")))] {
        // 只选择 feature1
    } else if #[cfg(all(not(feature = "royal_poker"), feature = "standard_poker", not(feature = "numeral_poker"), not(feature = "rust_waugh")))] {
        // 只选择 feature2
    } else if #[cfg(all(not(feature = "royal_poker"), not(feature = "standard_poker"), feature = "numeral_poker", not(feature = "rust_waugh")))] {
        // 只选择 feature3
    } else if #[cfg(all(not(feature = "royal_poker"), not(feature = "standard_poker"), not(feature = "numeral_poker"), feature = "rust_waugh"))] {
        // 只选择 feature3
    } else {
        compile_error!("One feature should be chosen");
    }
}

fn build(poker_game: &str) {
    let bindings = bindgen::Builder::default()
        // The input header we would like to generate
        // bindings for.
        .header("wrapper.h")
        // include path
        .clang_arg("-F./src/hand_isomorphism/")
        // define preprocessor marco
        .clang_arg(format!("-D {}", poker_game))
        // .whitelist_type("card_t")
        // .whitelist_var("RANK_TO_CHAR")
        // whitelist functions
        .allowlist_function("hand_indexer_init")
        .allowlist_function("hand_indexer_free")
        .allowlist_function("hand_indexer_size")
        .allowlist_function("hand_indexer_state_init")
        .allowlist_function("hand_index_all")
        .allowlist_function("hand_index_last")
        .allowlist_function("hand_index_next_round")
        .allowlist_function("hand_unindex")
        // Tell cargo to invalidate the built crate whenever any of the
        // included header files changed.
        .parse_callbacks(Box::new(bindgen::CargoCallbacks))
        // Finish the builder and generate the bindings.
        .generate()
        // Unwrap the Result and panic on failure.
        .expect("Unable to generate bindings");

    // Write the bindings to the $OUT_DIR/bindings.rs file.
    bindings
        .write_to_file("src/hand_isomorphism.rs")
        .expect("Couldn't write bindings!");

    cc::Build::new()
        .file("src/hand_isomorphism/hand-isomorphism/hand_index.c")
        .file("src/hand_isomorphism/hand-isomorphism/deck.c")
        .define(poker_game, None)
        .include("src/hand_isomorphism") //include 根目录
        .flag("-w") // 禁用警告
        .static_flag(true)
        .compile("hand_isomorphism");
}

fn main() {
    // 以下代码告诉 Cargo ，一旦指定的文件 `src/hello.c` 发生了改变，就重新运行当前的构建脚本
    println!("cargo:rerun-if-changed=wrapper.h");
    // 使用 `cc` 来构建一个 C 文件，然后进行静态链接

    // c语言中的条件编译宏变量
    const ROYAL_POKER: &str = "ROYAL_POKER";
    const STANDARD_POKER: &str = "STANDARD_POKER";
    const NUMERAL_POKER: &str = "NUMERAL_POKER";
    const RUST_WAUGH: &str = "RUST_WAUGH";

    if cfg!(feature = "standard_poker") {
        build(STANDARD_POKER);
    } else if cfg!(feature = "royal_poker") {
        build(ROYAL_POKER);
    } else if cfg!(feature = "numeral_poker") {
        build(NUMERAL_POKER);
    } else if cfg!(feature = "rust_waugh") {
        // build(RUST_WAUGH);
    }
}
