use std::collections::HashMap;
use std::sync::OnceLock;
use zpl_toolchain_profile::Profile;
use zpl_toolchain_spec_tables::ComparisonOp;
type ProfileFieldFn = fn(&Profile) -> Option<f64>;
const PROFILE_FIELD_REGISTRY: &[(&str, ProfileFieldFn)] = &[
("dpi", |p| Some(p.dpi as f64)),
("page.width_dots", |p| {
p.page
.as_ref()
.and_then(|pg| pg.width_dots.map(|v| v as f64))
}),
("page.height_dots", |p| {
p.page
.as_ref()
.and_then(|pg| pg.height_dots.map(|v| v as f64))
}),
("speed_range.min", |p| {
p.speed_range.as_ref().map(|r| r.min as f64)
}),
("speed_range.max", |p| {
p.speed_range.as_ref().map(|r| r.max as f64)
}),
("darkness_range.min", |p| {
p.darkness_range.as_ref().map(|r| r.min as f64)
}),
("darkness_range.max", |p| {
p.darkness_range.as_ref().map(|r| r.max as f64)
}),
("memory.ram_kb", |p| {
p.memory.as_ref().and_then(|m| m.ram_kb.map(|v| v as f64))
}),
("memory.flash_kb", |p| {
p.memory.as_ref().and_then(|m| m.flash_kb.map(|v| v as f64))
}),
];
static PROFILE_FIELD_MAP: OnceLock<HashMap<&'static str, ProfileFieldFn>> = OnceLock::new();
fn profile_field_map() -> &'static HashMap<&'static str, ProfileFieldFn> {
PROFILE_FIELD_MAP.get_or_init(|| PROFILE_FIELD_REGISTRY.iter().copied().collect())
}
pub fn resolve_profile_field(profile: &Profile, field: &str) -> Option<f64> {
profile_field_map().get(field).and_then(|f| f(profile))
}
pub(super) fn check_profile_op(value: f64, op: &ComparisonOp, limit: f64) -> bool {
if !value.is_finite() || !limit.is_finite() {
return false;
}
match op {
ComparisonOp::Lte => value <= limit,
ComparisonOp::Gte => value >= limit,
ComparisonOp::Lt => value < limit,
ComparisonOp::Gt => value > limit,
ComparisonOp::Eq => (value - limit).abs() < 0.5,
}
}