mod constrictor;
mod solo;
mod standard;

use constrictor::Constrictor;
use enum_dispatch::enum_dispatch;
use solo::Solo;
use standard::Standard;

use crate::types::{Direction, wire};

use super::Board;

#[enum_dispatch]
pub trait Ruleset {
    /// executes one turn of the ruleset.
    /// Returns true if the game is over
    fn execute(&self, board: &mut Board, actions: &[(u8, Direction)]) -> bool;
}

#[enum_dispatch(Ruleset)]
#[derive(Debug, Clone, Copy)]
pub enum Rulesets {
    Standard,
    Constrictor,
    Solo,
}

impl From<&wire::Ruleset> for Rulesets {
    fn from(value: &wire::Ruleset) -> Self {
        match value.name.as_ref() {
            "solo" => Solo::from(value).into(),
            "constrictor" => Constrictor::from(value).into(),
            _ => Standard::from(value).into(),
        }
    }
}
