use std::sync::LazyLock;
use crate::data::constants::{
CHINESE_TIME, EARTHLY_BRANCHES, FIVE_ELEMENTS_CLASSES, HEAVENLY_STEMS, SIGNS, ZODIAC,
};
use crate::data::stars::{ALL_STARS, MUTAGEN, StarKey};
use crate::data::types::*;
use super::{
translate_brightness, translate_earthly_branch, translate_five_elements_class,
translate_gender, translate_heavenly_stem, translate_horoscope_name, translate_mutagen,
translate_palace, translate_sign, translate_star, translate_time, translate_zodiac,
};
const LANGS: [Language; 6] = [
Language::ZhCN,
Language::ZhTW,
Language::EnUS,
Language::JaJP,
Language::KoKR,
Language::ViVN,
];
fn lang_index(lang: Language) -> usize {
LANGS.iter().position(|l| *l == lang).unwrap_or(0)
}
const MARKER_PALACES: [(&str, [&str; 6]); 2] = [
(
"bodyPalace",
["身宫", "身宮", "body", "身宮", "신궁", "Thân"],
),
(
"originalPalace",
["来因", "来因", "origin", "来因", "라인", "Lai Nhân"],
),
];
const GENDERS: [(&str, Gender); 2] = [("male", Gender::Male), ("female", Gender::Female)];
const HOROSCOPE_NAMES: [(&str, HoroscopeName); 7] = [
("decadal", HoroscopeName::Decadal),
("childhood", HoroscopeName::Childhood),
("yearly", HoroscopeName::Yearly),
("monthly", HoroscopeName::Monthly),
("daily", HoroscopeName::Daily),
("hourly", HoroscopeName::Hourly),
("turn", HoroscopeName::Age),
];
const LOOKUP_PALACE_KEYS: [&str; 14] = [
"soulPalace",
"bodyPalace",
"siblingsPalace",
"spousePalace",
"childrenPalace",
"wealthPalace",
"healthPalace",
"surfacePalace",
"friendsPalace",
"careerPalace",
"propertyPalace",
"spiritPalace",
"parentsPalace",
"originalPalace",
];
const BRIGHTNESSES: [Brightness; 7] = [
Brightness::Miao,
Brightness::Wang,
Brightness::De,
Brightness::Li,
Brightness::Ping,
Brightness::Bu,
Brightness::Xian,
];
pub fn translate_key(key: &str, lang: Language) -> Option<&'static str> {
if let Some(star) = StarKey::from_key(key) {
return Some(translate_star(star, lang));
}
if let Some(palace) = Palace::from_key(key) {
return Some(translate_palace(palace, lang));
}
if let Some((_, names)) = MARKER_PALACES.iter().find(|(k, _)| *k == key) {
return Some(names[lang_index(lang)]);
}
if let Some(stem) = HeavenlyStem::from_key(key) {
return Some(translate_heavenly_stem(stem, lang));
}
if let Some(branch) = EarthlyBranch::from_key(key) {
return Some(translate_earthly_branch(branch, lang));
}
if let Some(brightness) = Brightness::from_key(key) {
return Some(translate_brightness(brightness, lang));
}
if let Some(mutagen) = Mutagen::from_key(key) {
return Some(translate_mutagen(mutagen, lang));
}
if let Some(class) = FiveElementsClass::from_key(key) {
return Some(translate_five_elements_class(class, lang));
}
if let Some((_, gender)) = GENDERS.iter().find(|(k, _)| *k == key) {
return Some(translate_gender(*gender, lang));
}
if let Some(i) = ZODIAC.iter().position(|z| *z == key) {
return Some(translate_zodiac(EARTHLY_BRANCHES[i], lang));
}
if let Some(i) = CHINESE_TIME.iter().position(|t| *t == key) {
return Some(translate_time(i as u8, lang));
}
if let Some(i) = SIGNS.iter().position(|s| *s == key) {
return Some(translate_sign(i, lang));
}
if let Some((_, name)) = HOROSCOPE_NAMES.iter().find(|(k, _)| *k == key) {
return Some(translate_horoscope_name(*name, lang));
}
None
}
pub fn all_keys() -> Vec<&'static str> {
ALL_KEYS.clone()
}
static ALL_KEYS: LazyLock<Vec<&'static str>> = LazyLock::new(build_all_keys);
fn build_all_keys() -> Vec<&'static str> {
let mut keys: Vec<&'static str> = Vec::with_capacity(260);
keys.extend(HOROSCOPE_NAMES.iter().map(|(k, _)| *k));
keys.extend(ZODIAC);
keys.extend(CHINESE_TIME);
keys.extend(SIGNS);
keys.extend(FIVE_ELEMENTS_CLASSES.iter().map(|c| c.as_key()));
keys.extend(HEAVENLY_STEMS.iter().map(|s| s.as_key()));
keys.extend(EARTHLY_BRANCHES.iter().map(|b| b.as_key()));
keys.extend(BRIGHTNESSES.iter().map(|b| b.as_key()));
keys.extend(MUTAGEN.iter().map(|m| m.as_key()));
keys.extend(ALL_STARS.iter().map(|s| s.as_key()));
keys.extend(LOOKUP_PALACE_KEYS);
keys.extend(GENDERS.iter().map(|(k, _)| *k));
keys
}
const LOOKUP_LANGS: [Language; 6] = [
Language::EnUS,
Language::JaJP,
Language::KoKR,
Language::ZhCN,
Language::ZhTW,
Language::ViVN,
];
pub fn key_of(text: &str) -> Option<&'static str> {
key_of_matching(text, |_| true)
}
pub fn key_of_in(text: &str, key_filter: &str) -> Option<&'static str> {
key_of_matching(text, |key| key.contains(key_filter))
}
fn key_of_matching(text: &str, accept: impl Fn(&str) -> bool + Copy) -> Option<&'static str> {
LOOKUP_LANGS.iter().find_map(|lang| {
ALL_KEYS
.iter()
.copied()
.find(|key| accept(key) && translate_key(key, *lang) == Some(text))
})
}