use super::types::MunsellSpec;
use super::HUE_FAMILIES;
pub fn parse_hue_to_number(hue: &str) -> Option<f64> {
let families_by_length: [&str; 10] = ["YR", "GY", "BG", "PB", "RP", "R", "Y", "G", "B", "P"];
let (family, family_idx) = families_by_length
.iter()
.find_map(|&fam| {
if hue.ends_with(fam) {
let idx = HUE_FAMILIES.iter().position(|&f| f == fam)?;
Some((fam, idx))
} else {
None
}
})?;
let num_str = hue.strip_suffix(family)?;
let num: f64 = num_str.parse().ok()?;
if !(0.0..=10.0).contains(&num) {
return None;
}
let family_start = family_idx as f64 * 4.0;
let hue_number = (family_start + num / 2.5) % 40.0;
Some(hue_number)
}
pub fn hue_number_to_string(hue_number: f64) -> (String, &'static str) {
let normalized = ((hue_number % 40.0) + 40.0) % 40.0;
let within_family = (normalized % 4.0) * 2.5;
let (final_family_idx, final_num) = if within_family < 0.001 && normalized > 0.001 {
let prev_family_idx = ((normalized / 4.0).floor() as usize + 9) % 10;
(prev_family_idx, 10.0_f64)
} else if within_family < 0.001 {
(9, 10.0_f64) } else {
let family_idx = (normalized / 4.0).floor() as usize % 10;
(family_idx, within_family)
};
let final_family = HUE_FAMILIES[final_family_idx % 10];
let hue_str = if (final_num - final_num.round()).abs() < 0.001 {
format!("{}{}", final_num.round() as i32, final_family)
} else {
format!("{:.1}{}", final_num, final_family)
};
(hue_str, final_family)
}
pub fn parse_munsell_notation(notation: &str) -> Option<MunsellSpec> {
let notation = notation.trim();
if notation.starts_with("N ") {
let value_str = notation.strip_prefix("N ")?.trim_end_matches('/');
let value: f64 = value_str.parse().ok()?;
return Some(MunsellSpec::neutral(value));
}
let parts: Vec<&str> = notation.split_whitespace().collect();
if parts.len() != 2 {
return None;
}
let hue_number = parse_hue_to_number(parts[0])?;
let vc_parts: Vec<&str> = parts[1].split('/').collect();
if vc_parts.len() != 2 {
return None;
}
let value: f64 = vc_parts[0].parse().ok()?;
let chroma: f64 = vc_parts[1].parse().ok()?;
Some(MunsellSpec::new(hue_number, value, chroma))
}