use std::sync::{Arc, Mutex};
use crate::{registry::lock, types::FixtureSpec};
pub type FixtureHandler = Arc<dyn Fn(&str) -> Result<(), String> + Send + Sync>;
pub struct FixtureManager {
fixtures: Mutex<Vec<FixtureSpec>>,
handler: Mutex<Option<FixtureHandler>>,
}
impl FixtureManager {
pub fn new() -> Self {
Self {
fixtures: Mutex::new(Vec::new()),
handler: Mutex::new(None),
}
}
pub fn set_fixtures(&self, fixtures: Vec<FixtureSpec>) {
for fixture in &fixtures {
if let Err(error) = fixture.validate(true) {
panic!("invalid fixture {}: {error}", fixture.name);
}
}
let mut stored = lock(&self.fixtures, "fixtures lock");
*stored = fixtures;
}
pub fn fixtures(&self) -> Vec<FixtureSpec> {
lock(&self.fixtures, "fixtures lock").clone()
}
pub fn fixtures_sorted(&self) -> Vec<FixtureSpec> {
let mut fixtures = self.fixtures();
fixtures.sort_by(|a, b| a.name.cmp(&b.name));
fixtures
}
pub fn has_fixture(&self, name: &str) -> bool {
self.fixture(name).is_some()
}
pub fn fixture(&self, name: &str) -> Option<FixtureSpec> {
lock(&self.fixtures, "fixtures lock")
.iter()
.find(|fixture| fixture.name == name)
.cloned()
}
pub fn set_fixture_handler(&self, handler: FixtureHandler) {
*lock(&self.handler, "fixture handler lock") = Some(handler);
}
pub fn apply_fixture(&self, name: &str) -> Result<(), String> {
if !self.has_fixture(name) {
return Err(format!("unknown fixture: {name}"));
}
let handler = lock(&self.handler, "fixture handler lock").clone();
match handler {
Some(handler) => handler(name),
None => Err("no fixture handler registered".to_string()),
}
}
}