use rust_i18n::t;
use serde::{Deserialize, Serialize};
use crate::BadiDateError;
use super::util::*;
#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub enum BadiMonth {
Month(u8),
AyyamIHa,
}
impl Ord for BadiMonth {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
match self {
BadiMonth::Month(sm) => match other {
BadiMonth::Month(om) => sm.cmp(om),
BadiMonth::AyyamIHa => {
if *sm == 19 {
std::cmp::Ordering::Greater
} else {
std::cmp::Ordering::Less
}
}
},
BadiMonth::AyyamIHa => match other {
BadiMonth::Month(om) => {
if *om == 19 {
std::cmp::Ordering::Less
} else {
std::cmp::Ordering::Greater
}
}
BadiMonth::AyyamIHa => std::cmp::Ordering::Equal,
},
}
}
}
impl PartialOrd for BadiMonth {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl BadiMonth {
pub fn first() -> Self {
BadiMonth::Month(1)
}
pub fn last() -> Self {
BadiMonth::Month(19)
}
pub fn next(&self) -> Option<Self> {
match *self {
BadiMonth::Month(month) => match month.cmp(&18) {
std::cmp::Ordering::Less => Some(BadiMonth::Month(month + 1)),
std::cmp::Ordering::Equal => Some(BadiMonth::AyyamIHa),
std::cmp::Ordering::Greater => None,
},
BadiMonth::AyyamIHa => Some(BadiMonth::Month(19)),
}
}
pub fn previous(&self) -> Option<Self> {
match *self {
BadiMonth::Month(month) => {
if month == 1 {
None
} else if month == 19 {
Some(BadiMonth::AyyamIHa)
} else if month < 19 {
Some(BadiMonth::Month(month - 1))
} else {
None
}
}
BadiMonth::AyyamIHa => Some(BadiMonth::Month(18)),
}
}
pub fn validate(&self) -> Result<Self, BadiDateError> {
if match *self {
BadiMonth::Month(month) => (1..=19).contains(&month),
BadiMonth::AyyamIHa => true,
} {
return Ok(*self);
}
Err(BadiDateError::MonthInvalid(*self))
}
pub fn number_of_days(&self, year: u8) -> u16 {
match *self {
BadiMonth::Month(_) => 19,
BadiMonth::AyyamIHa => get_number_of_ayyamiha_days(year),
}
}
pub fn arabic(&self) -> String {
self.name("ar")
}
pub fn english(&self) -> String {
self.name("en")
}
pub fn transliteration(&self) -> String {
self.name("tl")
}
pub fn additional_meanings(&self) -> String {
self.name("extra")
}
pub fn name(&self, locale: &str) -> String {
match self {
BadiMonth::Month(month) => {
t!(format!("month.{}", month).as_str(), locale = locale).to_string()
}
BadiMonth::AyyamIHa => t!("ayyamiha", locale = locale).to_string(),
}
}
pub fn description(&self) -> String {
match self {
BadiMonth::Month(_) => format!("the month of {}", self.name("tl")),
BadiMonth::AyyamIHa => self.name("tl"),
}
}
}
#[cfg(test)]
mod tests {
use std::collections::HashSet;
use super::*;
#[test]
fn names() {
assert_eq!(
HashSet::<&str>::from_iter(vec!["ar", "en", "tl", "extra"]),
HashSet::<&str>::from_iter(rust_i18n::available_locales!())
);
assert_eq!("Bahá", BadiMonth::first().transliteration());
assert_eq!("كلمات", BadiMonth::Month(7).arabic());
assert_eq!("Words", BadiMonth::Month(7).english());
assert_eq!("Ayyám-i-Há", BadiMonth::AyyamIHa.transliteration());
}
}