//! Conformance corpus for co-performance (`live-conformance/coperformance/`, extensions/co-performance.md §11).
//!
//!   wai_co_performance_vectors gen    <corpus-dir>   write vectors.json, from fixed seeds
//!   wai_co_performance_vectors verify <corpus-dir>   vectors.json regenerates byte for byte, no
//!                                                    other file but README.md is there, and every
//!                                                    room gets the outcome it states
//!
//! The generator and this verifier are one implementation. The corpus's second
//! implementation is `live-conformance/co_performance_verify.py`, written from the extension's
//! text and sharing no code with this binary.

use std::collections::BTreeMap;
use std::path::Path;
use wai::co_performance::corpus;

fn main() {
    let a: Vec<String> = std::env::args().collect();
    match (a.get(1).map(String::as_str), a.get(2)) {
        (Some("gen"), Some(d)) => {
            if let Err(e) = std::fs::create_dir_all(d) {
                eprintln!("create {d}: {e}");
                std::process::exit(1);
            }
            for (name, body) in corpus::generate() {
                let p = Path::new(d).join(&name);
                if let Err(e) = std::fs::write(&p, body) {
                    eprintln!("write {}: {e}", p.display());
                    std::process::exit(1);
                }
            }
            println!("wrote {d}");
        }
        (Some("verify"), Some(d)) => std::process::exit(verify(Path::new(d))),
        _ => {
            eprintln!("usage: wai_co_performance_vectors gen|verify <corpus-dir>");
            std::process::exit(2);
        }
    }
}

fn verify(dir: &Path) -> i32 {
    let mut files = BTreeMap::new();
    let entries = match std::fs::read_dir(dir) {
        Ok(e) => e,
        Err(e) => {
            eprintln!("read {}: {e}", dir.display());
            return 1;
        }
    };
    for e in entries.flatten() {
        let name = e.file_name().to_string_lossy().into_owned();
        if name == "README.md" {
            continue;
        }
        match std::fs::read_to_string(e.path()) {
            Ok(s) => {
                files.insert(name, s);
            }
            Err(err) => {
                eprintln!("read {name}: {err}");
                return 1;
            }
        }
    }
    let generated: BTreeMap<String, String> = corpus::generate().into_iter().collect();
    let same = files == generated;
    println!("{} every file regenerates byte for byte from its seeds, and no other file is there", if same { "PASS" } else { "FAIL" });
    let fails = corpus::verify(&files);
    for f in &fails {
        println!("FAIL {f}");
    }
    println!("{} every room gets the outcome the corpus states", if fails.is_empty() { "PASS" } else { "FAIL" });
    (!same || !fails.is_empty()) as i32
}
