use std::str::FromStr;

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Language {
    Fr,
    En,
}

impl Language {
    pub const fn as_str(&self) -> &'static str {
        match self {
            Self::En => "en-US",
            Self::Fr => "fr-FR",
        }
    }
}

impl std::fmt::Display for Language {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.write_str(self.as_str())
    }
}

#[derive(Clone, Debug, thiserror::Error)]
pub enum LanguageParserError {
    #[error("unsupported language {_0:?}")]
    Unsupported(String),
}

impl std::str::FromStr for Language {
    type Err = LanguageParserError;

    fn from_str(input: &str) -> Result<Self, Self::Err> {
        match input {
            "en-US" => Ok(Language::En),
            "fr-FR" => Ok(Language::Fr),
            other => Err(LanguageParserError::Unsupported(other.to_string())),
        }
    }
}

impl serde::Serialize for Language {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: serde::Serializer,
    {
        serializer.serialize_str(self.as_str())
    }
}

impl<'de> serde::Deserialize<'de> for Language {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: serde::Deserializer<'de>,
    {
        let value = String::deserialize(deserializer)?;
        Language::from_str(value.as_str()).map_err(serde::de::Error::custom)
    }
}
