use crate::mosaic::ProjectSaveFile;
use crate::widgets::EditorWidget;
use nightshade::prelude::serde::{Deserialize, Serialize};
use std::collections::HashMap;

pub type EditorProjectFile = ProjectSaveFile<EditorWidget, EditorProjectData>;

#[derive(Clone, Serialize, Deserialize, Default)]
#[serde(crate = "nightshade::prelude::serde", default)]
pub struct EditorProjectData {
    pub scenes: HashMap<String, nightshade::ecs::scene::Scene>,
    pub active_layout_index: usize,
    pub active_scene_name: Option<String>,
}

impl EditorProjectData {
    pub fn active_scene(&self) -> Option<&nightshade::ecs::scene::Scene> {
        self.active_scene_name
            .as_ref()
            .and_then(|name| self.scenes.get(name))
    }

    pub fn add_scene(&mut self, name: String, scene: nightshade::ecs::scene::Scene) {
        self.scenes.insert(name.clone(), scene);
        if self.active_scene_name.is_none() {
            self.active_scene_name = Some(name);
        }
    }

    pub fn remove_scene(&mut self, name: &str) -> Option<nightshade::ecs::scene::Scene> {
        let removed = self.scenes.remove(name);
        if self.active_scene_name.as_deref() == Some(name) {
            self.active_scene_name = self.scenes.keys().next().cloned();
        }
        removed
    }

    pub fn set_active_scene(&mut self, name: &str) -> bool {
        if self.scenes.contains_key(name) {
            self.active_scene_name = Some(name.to_string());
            true
        } else {
            false
        }
    }
}

pub fn project_data(project: &EditorProjectFile) -> Option<&EditorProjectData> {
    project.data.as_ref()
}

pub(crate) fn project_data_mut(project: &mut EditorProjectFile) -> &mut EditorProjectData {
    project.data.get_or_insert_with(Default::default)
}

pub(crate) fn new_editor_project(name: Option<String>) -> EditorProjectFile {
    EditorProjectFile::new(name.unwrap_or_default(), env!("CARGO_PKG_VERSION"))
        .with_data(EditorProjectData::default())
}
