use serde::{de, Deserialize, Deserializer, Serialize, Serializer};

use crate::theme::{palette::Palette, THEMES};

#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub struct ColorScheme(usize);

impl ColorScheme {
    pub fn label(self) -> &'static str {
        THEMES[self.0].label
    }

    pub fn next(self) -> Self {
        Self((self.0 + 1) % THEMES.len())
    }

    pub fn prev(self) -> Self {
        Self((self.0 + THEMES.len() - 1) % THEMES.len())
    }

    pub fn to_palette(self) -> Palette {
        (THEMES[self.0].palette)()
    }
}

impl Serialize for ColorScheme {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        serializer.serialize_str(THEMES[self.0].id)
    }
}

impl<'de> Deserialize<'de> for ColorScheme {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        let s = String::deserialize(deserializer)?;
        THEMES
            .iter()
            .position(|t| t.id == s)
            .map(ColorScheme)
            .ok_or_else(|| de::Error::custom(format!("unknown theme: {s}")))
    }
}
