use serde::{Deserialize, Serialize};

/// Where a [`Script`]'s source comes from.
#[derive(Debug, Clone, Serialize, Deserialize, enum2schema::Schema)]
pub enum ScriptSource {
    Embedded { source: String },
    File { path: String },
}

impl Default for ScriptSource {
    fn default() -> Self {
        ScriptSource::Embedded {
            source: String::new(),
        }
    }
}

/// A rhai script attached to an entity. The runner compiles the source, runs its
/// `on_tick` each frame against a persistent per-entity scope, and applies the
/// commands the script appends to its `commands` array.
#[derive(Debug, Clone, Default, Serialize, Deserialize, enum2schema::Schema)]
pub struct Script {
    pub source: ScriptSource,
    #[serde(default = "default_enabled")]
    pub enabled: bool,
}

fn default_enabled() -> bool {
    true
}

impl Script {
    pub fn from_source(source: impl Into<String>) -> Self {
        Self {
            source: ScriptSource::Embedded {
                source: source.into(),
            },
            enabled: true,
        }
    }

    pub fn source_text(&self) -> &str {
        match &self.source {
            ScriptSource::Embedded { source } => source,
            ScriptSource::File { path } => path,
        }
    }
}

/// One scene-global script: a named, embedded rhai source with an enabled flag.
/// Unlike [`Script`], it is not attached to an entity. The runner executes every
/// enabled global script once per tick, in list order, before the per-entity
/// scripts, so global logic can set up scene state the entities then react to.
#[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize, enum2schema::Schema)]
pub struct GlobalScript {
    pub name: String,
    pub source: String,
    #[serde(default = "default_enabled")]
    pub enabled: bool,
}

impl GlobalScript {
    pub fn new(name: impl Into<String>) -> Self {
        Self {
            name: name.into(),
            source: "fn on_tick() {\n}\n".to_string(),
            enabled: true,
        }
    }
}

/// The scene's ordered list of global scripts. Lives in `world.resources` and
/// serializes with the scene, so the order is authored data the user controls.
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct GlobalScripts {
    pub entries: Vec<GlobalScript>,
}
