//! Conformance corpus for prior carriage (`live-conformance/prior-carriage/`,
//! extensions/prior-carriage.md §15; extensions/http-delivery.md §8.7).
//!
//!   wai_prior_carriage_vectors gen    <corpus-dir>   write the corpus, from the sets other
//!                                                      corpora commit and the cases written here
//!   wai_prior_carriage_vectors verify <corpus-dir>   every file regenerates byte for byte, no
//!                                                      other file but README.md is there, and
//!                                                      every case gets the outcome it states
//!
//! The generator and this verifier are one implementation. The corpus's second implementation
//! is `live-conformance/prior_carriage_verify.py`, written from the texts and sharing no code
//! with this binary.

use std::path::Path;
use wai::prior_carriage::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)) => std::process::exit(write_corpus(Path::new(d))),
        (Some("verify"), Some(d)) => std::process::exit(verify(Path::new(d))),
        _ => {
            eprintln!("usage: wai_prior_carriage_vectors gen|verify <corpus-dir>");
            std::process::exit(2);
        }
    }
}

fn write_corpus(dir: &Path) -> i32 {
    // The sets are read by their paths from this directory, so it exists first.
    if let Err(e) = std::fs::create_dir_all(dir) {
        eprintln!("create {}: {e}", dir.display());
        return 1;
    }
    let files = match corpus::generate(dir) {
        Ok(f) => f,
        Err(e) => {
            eprintln!("{e}");
            return 1;
        }
    };
    for (name, body) in files {
        let p = dir.join(&name);
        if let Some(parent) = p.parent() {
            if let Err(e) = std::fs::create_dir_all(parent) {
                eprintln!("create {}: {e}", parent.display());
                return 1;
            }
        }
        if let Err(e) = std::fs::write(&p, body) {
            eprintln!("write {}: {e}", p.display());
            return 1;
        }
    }
    println!("wrote {}", dir.display());
    0
}

fn verify(dir: &Path) -> i32 {
    let files = match corpus::committed(dir) {
        Ok(f) => f,
        Err(e) => {
            eprintln!("{e}");
            return 1;
        }
    };
    let same = match corpus::generate(dir) {
        Ok(g) => g == files,
        Err(e) => {
            eprintln!("{e}");
            false
        }
    };
    println!("{} every file regenerates byte for byte, and no other file is there", if same { "PASS" } else { "FAIL" });
    let fails = corpus::verify(dir, &files);
    for f in &fails {
        println!("FAIL {f}");
    }
    println!("{} every case gets the outcome the corpus states", if fails.is_empty() { "PASS" } else { "FAIL" });
    (!same || !fails.is_empty()) as i32
}
