use std::path::{Path, PathBuf};
fn collect(p: &Path, out: &mut Vec<PathBuf>) {
if p.is_dir() {
let Ok(rd) = std::fs::read_dir(p) else { return };
let mut v: Vec<PathBuf> = rd.flatten().map(|e| e.path()).collect();
v.sort();
for c in v {
collect(&c, out);
}
} else if p.extension().is_some_and(|e| e == "docx") {
out.push(p.to_path_buf());
}
}
pub fn run(args: &[String]) -> Result<(), String> {
let (limit, paths) = match args.iter().position(|a| a == "--over") {
Some(i) => {
let ms: f64 = args.get(i + 1).and_then(|s| s.parse().ok()).ok_or("--over needs milliseconds")?;
(ms, args.iter().enumerate().filter(|(k, _)| *k != i && *k != i + 1).map(|(_, a)| a.clone()).collect::<Vec<_>>())
}
None => (twip::layout::job::UNIT_LIMIT_MS, args.to_vec()),
};
twip::layout::job::time_units(limit);
let fonts = twip::font::Fonts::system();
let mut docs = Vec::new();
for p in &paths {
collect(Path::new(p), &mut docs);
}
let (mut over, mut laid) = (0, 0);
let mut worst: Vec<(f64, &'static str, String)> = Vec::new();
for path in &docs {
let Ok(bytes) = std::fs::read(path) else { continue };
let Ok(doc) = twip::docx::read(&bytes) else { continue };
twip::layout::job::take_over_limit();
twip::layout::layout(&doc, &fonts);
laid += 1;
for (class, ms) in twip::layout::job::take_over_limit() {
over += 1;
println!("{:8.2} ms {class:<14} {}", ms, path.display());
worst.push((ms, class, path.display().to_string()));
}
}
worst.sort_by(|a, b| b.0.total_cmp(&a.0));
println!("{laid} documents laid out; {over} units over {limit} ms");
if let Some((ms, class, path)) = worst.first() {
println!("longest: {ms:.2} ms ({class}) in {path}");
}
Ok(())
}