use indicatrix_cut_core::{Design, Edit, ScheduleState};
fn schedule_differs(current: &Design, variant: &Design) -> bool {
let mut probe = variant.clone();
probe.preform = current.preform;
probe.preform_y_offset = current.preform_y_offset;
probe.girdle_diameter_mm = current.girdle_diameter_mm;
probe.material = current.material.clone();
probe.concave_tiers.clone_from(¤t.concave_tiers);
probe != *current
}
const fn same_bits(a: f64, b: f64) -> bool {
a.to_bits() == b.to_bits()
}
fn edits_between(current: &Design, variant: &Design) -> Vec<Edit> {
let concave_differs = current.concave_tiers != variant.concave_tiers;
let mut edits = Vec::new();
if concave_differs {
edits.extend(
(0..current.concave_tiers.len())
.rev()
.map(|index| Edit::RemoveConcaveTier { index }),
);
}
if schedule_differs(current, variant) {
edits.push(Edit::ReplaceSchedule(Box::new(ScheduleState::of(variant))));
}
if current.preform != variant.preform {
edits.push(Edit::SetPreform {
preform: variant.preform,
});
}
if !same_bits(current.preform_y_offset, variant.preform_y_offset) {
edits.push(Edit::SetPreformYOffset {
y_offset: variant.preform_y_offset,
});
}
if current.girdle_diameter_mm.map(f64::to_bits) != variant.girdle_diameter_mm.map(f64::to_bits)
{
edits.push(Edit::SetGirdleDiameterMm {
girdle_diameter_mm: variant.girdle_diameter_mm,
});
}
if current.material != variant.material {
edits.push(Edit::SetMaterial {
material: variant.material.clone(),
});
}
if concave_differs {
edits.extend(
variant
.concave_tiers
.iter()
.enumerate()
.map(|(index, tier)| Edit::AddConcaveTier {
index,
tier: tier.clone(),
}),
);
}
edits
}
pub(super) fn open_label(name: &str) -> String {
format!("Open variant \"{}\"", name.trim())
}
pub(super) fn replacement_edit(current: &Design, variant: &Design) -> Result<Option<Edit>, String> {
if current == variant {
return Ok(None);
}
let mut edits = edits_between(current, variant);
let edit = if edits.len() == 1 {
edits.remove(0)
} else {
Edit::Batch(edits)
};
let mut scratch = current.clone();
scratch
.apply_edit(edit.clone())
.map_err(|error| format!("The design cannot take this variant. {error}"))?;
if scratch != *variant {
return Err("The design cannot be put back exactly as this variant was saved.".to_owned());
}
Ok(Some(edit))
}