//! Conformance corpus for exact tone mapping (`live-conformance/tonemap/`,
//! extensions/exact-tonemap.md §10).
//!
//!   wai_tonemap_vectors gen     <corpus-dir>   write vectors.json, frames.rgb8 and envelopes/
//!   wai_tonemap_vectors verify  <corpus-dir>   every file regenerates byte for byte, no other
//!                                              file but README.md is there, and every case and
//!                                              envelope gets the outcome it states
//!   wai_tonemap_vectors measure                §6's figures: each derivation against binary64
//!
//! The generator and this verifier are one implementation. The corpus's second
//! implementation is `live-conformance/tonemap_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::exact_tonemap::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)) => {
            for (name, body) in corpus::generate() {
                let p = Path::new(d).join(&name);
                if let Some(parent) = p.parent()
                    && let Err(e) = std::fs::create_dir_all(parent)
                {
                    eprintln!("create {}: {e}", parent.display());
                    std::process::exit(1);
                }
                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))),
        (Some("measure"), _) => {
            let c = corpus::build();
            for (k, (r, n, max, mean)) in corpus::measurement_figures(&c.measurement) {
                println!("{k}: {r} renditions, {n} samples, largest difference {max}, mean {mean}");
            }
        }
        _ => {
            eprintln!("usage: wai_tonemap_vectors gen|verify <corpus-dir> | measure");
            std::process::exit(2);
        }
    }
}

fn read_tree(dir: &Path, prefix: &str, out: &mut BTreeMap<String, Vec<u8>>) -> std::io::Result<()> {
    for e in std::fs::read_dir(dir)? {
        let e = e?;
        let name = format!("{prefix}{}", e.file_name().to_string_lossy());
        if e.file_type()?.is_dir() {
            read_tree(&e.path(), &format!("{name}/"), out)?;
        } else if name != "README.md" {
            out.insert(name, std::fs::read(e.path())?);
        }
    }
    Ok(())
}

fn verify(dir: &Path) -> i32 {
    let mut files = BTreeMap::new();
    if let Err(e) = read_tree(dir, "", &mut files) {
        eprintln!("read {}: {e}", dir.display());
        return 1;
    }
    let fails = corpus::verify(&files);
    for f in &fails {
        eprintln!("FAIL {f}");
    }
    if fails.is_empty() {
        println!("ok: {} files", files.len());
        0
    } else {
        1
    }
}
