use std::str::FromStr as _;

use serde::{Deserialize, Serialize};
use sqlx::{Decode, Postgres};

/// Languages represented as
/// [ISO 639-3 codes](https://en.wikipedia.org/wiki/List_of_ISO_639-3_codes).
#[derive(
    Clone,
    Debug,
    Deserialize,
    Eq,
    Hash,
    PartialEq,
    Serialize,
    strum::Display,
    strum::EnumIs,
    strum::EnumIter,
    strum::EnumString,
)]
#[serde(rename_all = "lowercase")]
#[strum(serialize_all = "lowercase")]
// NOTE: The [`sqlx::Encode`] and [`sqlx::Decode`] derive macros do not seem to
// use the [`strum`] serializations. The corresponding traits should be
// implemented explicitly (if used).
pub enum Language {
    Deu,
    Eng,
    Spa,
}

impl Language {
    /// Returns language name to be presented in UI.
    pub fn as_locale_str(&self) -> &'static str {
        match self {
            Self::Deu => "Deutsch",
            Self::Eng => "English",
            Self::Spa => "Español",
        }
    }
}

impl Default for Language {
    /// Language defaults to English when necessary, as the product is being
    /// developed with a primarily English speaking/reading/writing market in
    /// mind.
    fn default() -> Self {
        Self::Eng
    }
}

impl Decode<'_, Postgres> for Language {
    fn decode(
        value: <Postgres as sqlx::Database>::ValueRef<'_>,
    ) -> Result<Self, sqlx::error::BoxDynError> {
        let value = <&str as Decode<Postgres>>::decode(value)?;
        Ok(Self::from_str(value)?)
    }
}
