use std::collections::HashMap;
use std::path::PathBuf;
use serde_yaml::Value;
use super::manifest::{EntityManifest, SceneManifest, load_entity_manifest, ManifestLoaderError};
#[derive(Debug, thiserror::Error)]
pub enum SolverError {
#[error("Manifest loader error: {0}")]
ManifestLoader(#[from] ManifestLoaderError),
#[error("Template not found: {0}")]
TemplateNotFound(String),
#[error("Component merge error: {0}")]
ComponentMerge(String),
}
pub struct ResolvedScene {
pub entities: HashMap<String, HashMap<String, Value>>,
}
pub struct ManifestSolver {
entity_cache: HashMap<String, EntityManifest>,
base_path: PathBuf,
}
impl ManifestSolver {
pub fn new<P: Into<PathBuf>>(base_path: P) -> Self {
Self {
entity_cache: HashMap::new(),
base_path: base_path.into(),
}
}
pub fn resolve_scene(&mut self, scene: &SceneManifest) -> Result<ResolvedScene, SolverError> {
let mut resolved = HashMap::new();
for (name, entity_instance) in &scene.entities {
let components = if let Some(template) = &entity_instance.template {
let template_manifest = self.load_template(template)?;
Self::merge_components(&template_manifest.components, &entity_instance.components)?
} else {
entity_instance.components.clone()
};
resolved.insert(name.clone(), components);
}
Ok(ResolvedScene { entities: resolved })
}
fn load_template(&mut self, template_path: &str) -> Result<&EntityManifest, SolverError> {
if !self.entity_cache.contains_key(template_path) {
let full_path = self.base_path.join("world").join("entities").join(format!("{}.yaml", template_path));
let manifest = load_entity_manifest(full_path)?;
self.entity_cache.insert(template_path.to_string(), manifest);
}
Ok(&self.entity_cache[template_path])
}
fn merge_components(
template_components: &HashMap<String, Value>,
overrides: &HashMap<String, Value>
) -> Result<HashMap<String, Value>, SolverError> {
let mut merged = template_components.clone();
for (key, value) in overrides {
merged.insert(key.clone(), value.clone());
}
Ok(merged)
}
}