Documentation
use std::{fmt::Display, str::FromStr};

/// Describes a generic font family.
#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
pub enum Generic {
	/// Glyphs have finishing strokes, flared or tapering ends, or have actual
	///  serifed endings.
	Serif = 0,
	/// Glyphs have stroke endings that are plain.
	SansSerif = 1,
	/// All glyphs have the same fixed width.
	Monospace = 2,
	/// Glyphs in cursive fonts generally have either joining strokes or other
	/// cursive characteristics beyond those of italic typefaces. The glyphs
	/// are partially or completely connected, and the result looks more like
	/// handwritten pen or brush writing than printed letter work.
	Cursive = 3,
	/// Fantasy fonts are primarily decorative fonts that contain playful
	/// representations of characters
	Fantasy = 4,
	/// Glyphs are taken from the default user interface font on a given
	/// platform.
	SystemUi = 5,
	/// The default user interface serif font.
	UiSerif = 6,
	/// The default user interface sans-serif font.
	UiSansSerif = 7,
	/// The default user interface monospace font.
	UiMonospace = 8,
	/// The default user interface font that has rounded features.
	UiRounded = 9,
	/// Fonts that are specifically designed to render emoji.
	Emoji = 10,
	/// This is for the particular stylistic concerns of representing
	/// mathematics: superscript and subscript, brackets that cross several
	/// lines, nesting expressions, and double struck glyphs with distinct
	/// meanings.
	Math = 11,
	/// A particular style of Chinese characters that are between serif-style
	/// Song and cursive-style Kai forms. This style is often used for
	/// government documents.
	FangSong = 12,
}
impl Default for Generic {
	fn default() -> Self {
		Self::SystemUi
	}
}
// Generic Family Map
impl FromStr for Generic {
	type Err = &'static str;
	fn from_str(s: &str) -> Result<Self, Self::Err> {
		Ok(match s.trim() {
			"serif" => Self::Serif,
			"sans-serif" => Self::SansSerif,
			"monospace" => Self::Monospace,
			"cursive" => Self::Cursive,
			"fantasy" => Self::Fantasy,
			"system-ui" | "system" | "" => Self::SystemUi,
			"ui-serif" => Self::UiSerif,
			"ui-sans-serif" => Self::UiSansSerif,
			"ui-monospace" => Self::UiMonospace,
			"ui-rounded" => Self::UiRounded,
			"emoji" => Self::Emoji,
			"math" => Self::Math,
			"fangsong" => Self::FangSong,
			_ => return Err("fail"),
		})
	}
}
impl Display for Generic {
	fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
		let name = match self {
			Self::Serif => "serif",
			Self::SansSerif => "sans-serif",
			Self::Monospace => "monospace",
			Self::Cursive => "cursive",
			Self::Fantasy => "fantasy",
			Self::SystemUi => "system-ui",
			Self::UiSerif => "ui-serif",
			Self::UiSansSerif => "ui-sans-serif",
			Self::UiMonospace => "ui-monospace",
			Self::UiRounded => "ui-rounded",
			Self::Emoji => "emoji",
			Self::Math => "math",
			Self::FangSong => "fangsong",
		};
		write!(f, "{}", name)
	}
}
impl Generic {
	#[cfg(target_os = "android")]
	pub fn system(&self) -> &'static str {
		// fonts.xml have alias
		match *self {
			Self::Serif => "serif",
			Self::SansSerif => "sans-serif",
			Self::Monospace => "monospace",
			Self::Cursive => "cursive",
			Self::Fantasy => "cursive", // no fantasy in fonts.xml
			Self::SystemUi => "sans-serif",
			Self::Emoji => "sans-serif",
			_ => "sans-serif",
		}
	}
	#[cfg(target_os = "linux")]
	pub fn system(&self) -> &'static str {
		// fonts.conf have alias
		match *self {
			Self::Serif => "serif",
			Self::SansSerif => "sans-serif",
			Self::Monospace => "monospace",
			Self::Cursive => "cursive",
			Self::Fantasy => "fantasy",
			Self::SystemUi => "system-ui",
			Self::UiSerif => "serif",
			Self::UiSansSerif => "sans-serif",
			Self::UiMonospace => "monospace",
			Self::Emoji => "emoji",
			Self::Math => "math",
			_ => "sans-serif",
		}
	}
	#[cfg(any(target_os = "ios", target_os = "macos"))]
	pub fn system(&self) -> &'static str {
		// from fontique
		// const DEFAULT_GENERIC_FAMILIES: &[(GenericFamily, &[&str])] = &[
		// 	(GenericFamily::Serif, &["Times", "Times New Roman"]),
		// 	(GenericFamily::SansSerif, &["Helvetica"]),
		// 	(GenericFamily::Monospace, &["Courier", "Courier New"]),
		// 	(GenericFamily::Cursive, &["Apple Chancery"]),
		// 	(GenericFamily::Fantasy, &["Papyrus"]),
		// 	(GenericFamily::SystemUi, &["System Font", ".SF NS"]),
		// 	(GenericFamily::Emoji, &["Apple Color Emoji"]),
		// 	(GenericFamily::Math, &["STIX Two Math"]),
		// ];
		// from godot
		// String OS_IOS::_get_default_fontname(const String &p_font_name) const {
		// 	String font_name = p_font_name;
		// 	if (font_name.to_lower() == "sans-serif") {
		// 		font_name = "Helvetica";
		// 	} else if (font_name.to_lower() == "serif") {
		// 		font_name = "Times";
		// 	} else if (font_name.to_lower() == "monospace") {
		// 		font_name = "Courier";
		// 	} else if (font_name.to_lower() == "fantasy") {
		// 		font_name = "Papyrus";
		// 	} else if (font_name.to_lower() == "cursive") {
		// 		font_name = "Apple Chancery";
		// 	};
		// 	return font_name;
		// }
		match *self {
			Generic::Serif => "Times New Roman",
			Generic::SansSerif => "Helvetica",
			Generic::Monospace => "Courier New",
			Generic::Cursive => "Apple Chancery",
			Generic::Fantasy => "Papyrus",
			Generic::SystemUi => "System Font",
			Generic::Emoji => "Apple Color Emoji",
			Generic::Math => "STIX Two Math",
			_ => "System Font",
		}
	}
	#[cfg(target_os = "windows")]
	pub fn system(&self) -> &'static str {
		// https://learn.microsoft.com/en-us/windows/win32/uxguide/vis-fonts
		// const DEFAULT_GENERIC_FAMILIES: &[(GenericFamily, &[&str])] = &[
		// 	(GenericFamily::Serif, &["Times New Roman"]),
		// 	(GenericFamily::SansSerif, &["Arial"]),
		// 	(GenericFamily::Monospace, &["Consolas"]),
		// 	(GenericFamily::Cursive, &["Comic Sans MS"]),
		// 	(GenericFamily::Fantasy, &["Impact"]),
		// 	(GenericFamily::SystemUi, &["Segoe UI"]),
		// 	(GenericFamily::Emoji, &["Segoe UI Emoji"]),
		// 	(GenericFamily::Math, &["Cambria Math"]),
		// 	(GenericFamily::FangSong, &["FangSong"]),
		// ];
		// String OS_Windows::_get_default_fontname(const String &p_font_name) const {
		// 	String font_name = p_font_name;
		// 	if (font_name.to_lower() == "sans-serif") {
		// 		font_name = "Arial";
		// 	} else if (font_name.to_lower() == "serif") {
		// 		font_name = "Times New Roman";
		// 	} else if (font_name.to_lower() == "monospace") {
		// 		font_name = "Courier New";
		// 	} else if (font_name.to_lower() == "cursive") {
		// 		font_name = "Comic Sans MS";
		// 	} else if (font_name.to_lower() == "fantasy") {
		// 		font_name = "Gabriola";
		// 	}
		// 	return font_name;
		// }
		match *self {
			Generic::Serif => "Times New Roman",
			Generic::SansSerif => "Arial",
			Generic::Monospace => "Courier New",
			Generic::Cursive => "Comic Sans MS",
			Generic::Fantasy => "Gabriola",
			Generic::SystemUi => "Segoe UI",
			Generic::Emoji => "Segoe UI Emoji",
			Generic::Math => "Cambria Math",
			Generic::FangSong => "FangSong",
			_ => "Segoe UI",
		}
	}
	#[cfg(target_arch = "wasm32")]
	pub fn system(&self) -> &'static str {
		match *self {
			Self::Serif => "serif",
			Self::SansSerif => "sans-serif",
			Self::Monospace => "monospace",
			Self::Cursive => "cursive",
			Self::Fantasy => "fantasy",
			Self::SystemUi => "system-ui",
			Self::UiSerif => "ui-serif",
			Self::UiSansSerif => "ui-sans-serif",
			Self::UiMonospace => "ui-monospace",
			Self::UiRounded => "ui-rounded",
			Self::Emoji => "emoji",
			Self::Math => "math",
			Self::FangSong => "fangsong",
		}
	}
}