use crate::evok::types::CommandType;
use serde::{Deserialize, Serialize};
use std::fmt::{Display, Formatter, Result};

#[derive(Serialize, Deserialize, Debug)]
pub struct SetCommand {
    pub cmd: CommandType,
    pub dev: String,
    pub circuit: String,
    // eg. RelayInput but Stringified without parent brackets
    pub data: String,
}

impl SetCommand {
    pub fn new(dev: String, circuit: String, data: String) -> Self {
        Self {
            cmd: CommandType::Set,
            dev,
            circuit,
            data,
        }
    }
}

impl Display for SetCommand {
    fn fmt(&self, f: &mut Formatter) -> Result {
        write!(
            f,
            "{{\"cmd\":\"{}\", \"dev\":\"{}\", \"circuit\": \"{}\", {}}}",
            self.cmd, self.dev, self.circuit, self.data
        )
    }
}

#[derive(Serialize, Deserialize, Debug)]
pub struct AllCommand {
    pub cmd: CommandType,
}

impl AllCommand {
    pub fn new() -> Self {
        Self {
            cmd: CommandType::All,
        }
    }
}

impl Default for AllCommand {
    fn default() -> Self {
        Self::new()
    }
}

#[derive(Serialize, Deserialize, Debug)]
pub struct FilterCommand {
    pub cmd: CommandType,
    pub devices: Vec<String>,
}

impl FilterCommand {
    pub fn new(devices: &[&str]) -> Self {
        let mut temp: Vec<String> = Vec::new();
        for device in devices {
            temp.push(device.to_string());
        }
        Self {
            cmd: CommandType::Filter,
            devices: temp,
        }
    }
}
