use crate::{Result, SpectroError};
use directories::ProjectDirs;
use serde::{Deserialize, Serialize};
use std::fs;
use std::path::PathBuf;
#[derive(Debug, Serialize, Deserialize)]
pub struct CalibrationData {
pub serial: String,
pub timestamp: u64,
pub dark_ref: Vec<u16>,
pub white_cal_factors: Vec<f32>,
}
fn get_config_dir() -> Result<PathBuf> {
let dirs = ProjectDirs::from("com", "tinnci", "spectro-rs")
.ok_or_else(|| SpectroError::Device("Could not determine config directory".into()))?;
let path = dirs.config_dir();
if !path.exists() {
fs::create_dir_all(path)
.map_err(|e| SpectroError::Device(format!("Failed to create config dir: {}", e)))?;
}
Ok(path.to_path_buf())
}
fn get_cal_path(serial: &str) -> Result<PathBuf> {
let mut path = get_config_dir()?;
path.push(format!("cal_{}.json", serial));
Ok(path)
}
pub fn save_calibration(serial: &str, dark_ref: &[u16], factors: &[f32]) -> Result<()> {
let data = CalibrationData {
serial: serial.to_string(),
timestamp: std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap_or_default()
.as_secs(),
dark_ref: dark_ref.to_vec(),
white_cal_factors: factors.to_vec(),
};
let path = get_cal_path(serial)?;
let json = serde_json::to_string_pretty(&data)
.map_err(|e| SpectroError::Device(format!("Serialization error: {}", e)))?;
fs::write(path, json)
.map_err(|e| SpectroError::Device(format!("Failed to write calibration file: {}", e)))?;
Ok(())
}
pub fn load_calibration(serial: &str) -> Result<Option<CalibrationData>> {
let path = get_cal_path(serial)?;
if !path.exists() {
return Ok(None);
}
let json = fs::read_to_string(path)
.map_err(|e| SpectroError::Device(format!("Failed to read calibration file: {}", e)))?;
let data: CalibrationData = serde_json::from_str(&json)
.map_err(|e| SpectroError::Device(format!("Deserialization error: {}", e)))?;
Ok(Some(data))
}