use serde::Deserialize;
use std::{collections::HashMap, env, fs, path::Path};

fn main() {
	let out_dir = env::var_os("OUT_DIR").unwrap();
	let out_dir = Path::new(&out_dir);

	// Get maud version and write it to OUT_DIR/maud.txt
	let cargo_toml: CargoToml = toml::from_str(include_str!("Cargo.toml")).unwrap();
	let maud = cargo_toml.dependencies.get("maud").unwrap();
	let version = maud.version();
	fs::write(out_dir.join("maud.txt"), version).unwrap();

	// Create an enum of available locales
	let locale_files = fs::read_dir("locales")
		.unwrap()
		.map(|e| e.unwrap())
		.collect::<Vec<_>>();
	let locales = locale_files
		.iter()
		.map(|e| e.path().with_extension(""))
		.map(|p| {
			// Capitalize the first character of the filename
			let id = p.file_name().unwrap().to_str().unwrap();
			let mut chars = id.chars();
			let ident = match chars.next() {
				None => String::new(), // nothing to capitalize
				Some(first) => first.to_uppercase().collect::<String>() + chars.as_str(),
			};
			(id.to_string(), ident)
		});

	let locale_idents = locales
		.clone()
		.map(|(id, ident)| format!("\t/// `{id}`\n\t{ident},"));
	let locale_displays = locales
		.clone()
		.map(|(id, ident)| format!("\t\t\tSelf::{ident} => \"{id}\","));
	let locale_idents_list = locales.map(|(_, ident)| format!("\t\t\tSelf::{ident},"));

	let locales_enum = format!(
		r##"#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum LangImpl {{
	/// The debug lang, `qqx`.
	Qqx,
{}
}}

impl ::core::fmt::Display for LangImpl {{
	#[inline]
	fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {{
		write!(f, "{{}}", self.as_str())
	}}
}}

impl LangImpl {{
	/// Returns the ID of the lang, e.g. `"en"`.
	#[inline]
	pub const fn as_str(&self) -> &'static str {{
		match self {{
			Self::Qqx => "qqx",
{}
		}}
	}}

	/// The list of all `LangImpl` values available to users.
	#[inline]
	pub const fn all() -> &'static [Self] {{
		&[
{}
		]
	}}
}}
"##,
		locale_idents.collect::<Vec<_>>().join("\n"),
		locale_displays.collect::<Vec<_>>().join("\n"),
		locale_idents_list.collect::<Vec<_>>().join("\n"),
	);
	fs::write(out_dir.join("langs.rs"), locales_enum).unwrap();

	println!("cargo::rerun-if-changed=build.rs,Cargo.toml,locales");
}

#[derive(Deserialize)]
struct CargoToml {
	dependencies: HashMap<String, PackageManifest>,
}

#[derive(Deserialize)]
#[serde(untagged)]
enum PackageManifest {
	Version(String),
	Manifest { version: String },
}

impl PackageManifest {
	const fn version(&self) -> &str {
		match self {
			Self::Version(version) => version.as_str(),
			Self::Manifest { version } => version.as_str(),
		}
	}
}
