use std::{rc::Rc, sync::LazyLock};

use super::{Environment, Node, NodeEnum, Precedence};

#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub struct Empty {
    message: Option<String>,
}

impl Node for Empty {
    fn evaluate(&self, _: &mut Environment) -> Result<Rc<NodeEnum>, String> {
        Ok(Empty::EMPTY.clone())
    }

    fn as_string(&self, _: Option<&Environment>) -> String {
        match &self.message {
            Some(m) => m.clone(),
            None => String::from("{{#VOID}}"),
        }
    }

    fn precedence(&self) -> Precedence {
        Precedence::Empty
    }
}

impl Empty {
    pub const EMPTY: LazyLock<Rc<NodeEnum>> =
        LazyLock::new(|| Rc::new(Empty { message: None }.into()));

    pub fn new(message: impl Into<String>) -> Rc<NodeEnum> {
        Rc::new(
            Self {
                message: Some(message.into()),
            }
            .into(),
        )
    }
}
