use std::collections::BTreeMap;
use std::path::{Path, PathBuf};
use std::sync::{Arc, Mutex};
use serde::Serialize;
use crate::kicad::Comparison;
#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
pub(super) struct KicadStatus {
pub board: String,
pub file: String,
pub state: &'static str,
pub differences: Vec<String>,
pub message: Option<String>,
}
impl KicadStatus {
pub(super) fn new(board: &str, file: &str, result: Result<Comparison, String>) -> Self {
let status = |state, differences, message| Self {
board: board.to_string(),
file: file.to_string(),
state,
differences,
message,
};
match result {
Err(message) => status("error", Vec::new(), Some(message)),
Ok(comparison) => {
let mut differences = comparison.differences.clone();
differences.extend(
comparison
.moved()
.iter()
.map(|name| format!("{name} placement differs")),
);
match differences.is_empty() {
true => status("in_sync", differences, None),
false => status("differs", differences, None),
}
}
}
}
}
#[derive(Clone)]
pub(super) struct KicadStates {
all: Arc<Mutex<BTreeMap<String, KicadStatus>>>,
backup: PathBuf,
}
impl Default for KicadStates {
fn default() -> Self {
Self {
all: Arc::default(),
backup: PathBuf::from(".fusible/backup"),
}
}
}
impl KicadStates {
pub(super) fn backup_dir(&self) -> &Path {
&self.backup
}
#[cfg(test)]
pub(super) fn with_backup(dir: PathBuf) -> Self {
Self {
backup: dir,
..Self::default()
}
}
pub(super) fn set(&self, status: KicadStatus) -> bool {
let Ok(mut all) = self.all.lock() else {
return false;
};
all.insert(status.board.clone(), status.clone()) != Some(status)
}
pub(super) fn json(&self) -> String {
let all: Vec<KicadStatus> = self
.all
.lock()
.map(|all| all.values().cloned().collect())
.unwrap_or_default();
serde_json::to_string(&all).unwrap_or_else(|_| "[]".into())
}
pub(super) fn event(&self) -> String {
format!(r#"{{"event":"sync","boards":{}}}"#, self.json())
}
}