//! Does a resource's DESCRIPTOR carry its bounding box?
//!
//! The last cross-container disagreements are 24-vertex bound boxes swapping
//! identities; no anchoring rule can pin them (see docs). If the descriptor
//! states the box, that is the missing information. This decodes the resource,
//! takes the box its geometry actually spans, and searches the descriptor for
//! those float values.
//!
//! Usage: bounds_in_descriptor <container.xpr> <resource>...
use sylpheed_formats::mesh::{xbg7_descriptor_range, Xbg7Model};
use std::collections::HashSet;

fn main() {
    let a: Vec<String> = std::env::args().collect();
    let bytes = std::fs::read(&a[1]).expect("container");
    let want: HashSet<String> = a[2..].iter().cloned().collect();
    for m in Xbg7Model::models_named(&bytes, &want, &|| false) {
        let (mut lo, mut hi) = ([f32::MAX; 3], [f32::MIN; 3]);
        for s in &m.meshes {
            for q in &s.positions {
                for k in 0..3 {
                    lo[k] = lo[k].min(q[k]);
                    hi[k] = hi[k].max(q[k]);
                }
            }
        }
        let Some((d0, d1)) = xbg7_descriptor_range(&bytes, &m.name) else { continue };
        println!(
            "{} descriptor 0x{d0:x}..0x{d1:x} ({} bytes), box lo{:?} hi{:?}",
            m.name,
            d1 - d0,
            lo.map(|v| v.round()),
            hi.map(|v| v.round())
        );
        // Where in the descriptor does each bound value appear (±0.01)?
        let targets: Vec<(&str, f32)> = vec![
            ("lo.x", lo[0]), ("lo.y", lo[1]), ("lo.z", lo[2]),
            ("hi.x", hi[0]), ("hi.y", hi[1]), ("hi.z", hi[2]),
        ];
        for (label, v) in targets {
            let mut at: Vec<usize> = Vec::new();
            let mut o = d0;
            while o + 4 <= d1 {
                let f = f32::from_be_bytes(bytes[o..o + 4].try_into().unwrap());
                if (f - v).abs() <= 0.01 * (1.0 + v.abs()) {
                    at.push(o - d0);
                }
                o += 4;
            }
            println!("   {label:5} {v:10.3} at descriptor offsets {:x?}", &at[..at.len().min(6)]);
        }
    }
}
