use std::rc::Rc;

use super::{if_else::Bool, Environment, Error, Node, NodeEnum, Precedence};

#[derive(Clone, Debug, PartialEq, PartialOrd)]
pub struct Equals {
    left: Rc<NodeEnum>,
    right: Vec<Rc<NodeEnum>>,
}

impl Node for Equals {
    fn evaluate(&self, env: &mut Environment) -> Result<Rc<NodeEnum>, Error> {
        let left = self.left.evaluate(env)?;

        for expr in &self.right {
            if left != expr.evaluate(env)? {
                return Ok(Rc::new(Bool::False.into()));
            }
        }

        return Ok(Rc::new(Bool::True.into()));
    }

    fn as_string(&self, env: Option<&Environment>) -> String {
        format!(
            "{} = {}",
            self.left.as_string(env),
            self.right
                .iter()
                .map(|x| x.as_string(env))
                .reduce(|a, b| a + " = " + &b)
                .unwrap()
        )
    }

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

impl Equals {
    pub fn new(left: Rc<NodeEnum>, right: Vec<Rc<NodeEnum>>) -> Self {
        Self { left, right }
    }
}
