use std::path::Path;
use super::changes::design_differences;
use super::diff::{compare_kicad_with_circuit, parse_circuit_elements, DiffReport, PlacementDiff};
use super::sexpr::{extract_footprints, parse_sexpr};
use super::tsx::rewrite_tree;
pub struct Comparison {
report: DiffReport,
pub differences: Vec<String>,
}
impl Comparison {
pub fn moved(&self) -> Vec<String> {
self.report
.diffs
.iter()
.filter(|d| d.is_placement_change())
.map(|d| d.designator.clone())
.collect()
}
}
pub fn compare_board(pcb: &Path, circuit_json: &str) -> Result<Comparison, String> {
let content =
std::fs::read_to_string(pcb).map_err(|e| format!("cannot read {}: {e}", pcb.display()))?;
let sexpr = parse_sexpr(&content).map_err(|e| format!("invalid KiCad file: {e}"))?;
let footprints = extract_footprints(&sexpr);
let elements =
parse_circuit_elements(circuit_json).map_err(|e| format!("invalid Circuit JSON: {e}"))?;
let report = compare_kicad_with_circuit(&footprints, &elements);
let differences = design_differences(&report, &footprints, &elements);
Ok(Comparison {
report,
differences,
})
}
pub fn sync_positions(
comparison: &Comparison,
dir: &Path,
backup_dir: &Path,
name: &str,
) -> Result<Vec<String>, String> {
let moved: Vec<&PlacementDiff> = comparison
.report
.diffs
.iter()
.filter(|d| d.is_placement_change())
.collect();
match moved.is_empty() {
true => Ok(Vec::new()),
false => rewrite_tree(dir, &moved, backup_dir, name),
}
}