use sha2::{Digest, Sha256};
use std::env;
use std::fs;
use std::path::PathBuf;

const MAX_ZERO_HASH_DEPTH: usize = 64;

fn hash_nodes(left: &[u8; 32], right: &[u8; 32]) -> [u8; 32] {
    let mut hasher = Sha256::new();
    hasher.update(left);
    hasher.update(right);
    let out = hasher.finalize();
    let mut bytes = [0u8; 32];
    bytes.copy_from_slice(&out);
    bytes
}

fn main() {
    let mut hashes: Vec<[u8; 32]> = Vec::with_capacity(MAX_ZERO_HASH_DEPTH + 1);
    hashes.push([0u8; 32]);
    for i in 1..=MAX_ZERO_HASH_DEPTH {
        let prev = hashes[i - 1];
        hashes.push(hash_nodes(&prev, &prev));
    }

    let mut out = String::new();
    out.push_str("// @generated by build.rs\n");
    out.push_str("pub const MAX_ZERO_HASH_DEPTH: usize = 64;\n");
    out.push_str("pub static ZERO_HASHES: [[u8; 32]; 65] = [\n");
    for h in &hashes {
        out.push_str("    [");
        for (i, b) in h.iter().enumerate() {
            if i != 0 {
                out.push_str(", ");
            }
            out.push_str(&format!("{b}"));
        }
        out.push_str("],\n");
    }
    out.push_str("];\n");

    let out_dir = PathBuf::from(env::var("OUT_DIR").expect("OUT_DIR is set by cargo"));
    fs::write(out_dir.join("zero_hashes.rs"), out).expect("write zero_hashes.rs");
}
