defmodule Money.Input.Components.Flags do
@moduledoc false
# Currency-code → Unicode regional-indicator flag glyph.
#
# Built from a static currency → primary territory table. The
# flag itself is generated by pairing the territory's two ASCII
# letters with the Unicode regional-indicator-symbol base
# (U+1F1E6), which renderers compose into the flag emoji.
#
# For currencies whose canonical territory is supranational
# (EUR → European Union → 🇪🇺) or non-geographic (XAU gold,
# XDR), we fall back to a neutral white-flag glyph so the row
# still renders.
@currency_to_territory %{
USD: "US",
CAD: "CA",
EUR: "EU",
GBP: "GB",
JPY: "JP",
CHF: "CH",
AUD: "AU",
NZD: "NZ",
CNY: "CN",
HKD: "HK",
SGD: "SG",
KRW: "KR",
INR: "IN",
BRL: "BR",
MXN: "MX",
ZAR: "ZA",
SEK: "SE",
NOK: "NO",
DKK: "DK",
PLN: "PL",
CZK: "CZ",
HUF: "HU",
RON: "RO",
TRY: "TR",
RUB: "RU",
ILS: "IL",
AED: "AE",
SAR: "SA",
EGP: "EG",
THB: "TH",
IDR: "ID",
PHP: "PH",
MYR: "MY",
VND: "VN",
TWD: "TW",
UAH: "UA",
ARS: "AR",
COP: "CO",
PEN: "PE",
CLP: "CL",
PKR: "PK",
BDT: "BD",
NGN: "NG",
KES: "KE",
KZT: "KZ",
MAD: "MA",
BHD: "BH",
KWD: "KW",
QAR: "QA",
OMR: "OM",
JOD: "JO",
LKR: "LK",
NPR: "NP",
ISK: "IS",
BGN: "BG",
HRK: "HR",
RSD: "RS",
UYU: "UY",
DOP: "DO",
GTQ: "GT",
PAB: "PA",
HNL: "HN",
NIO: "NI",
JMD: "JM",
BBD: "BB",
BSD: "BS",
XCD: "AG",
BMD: "BM",
KYD: "KY",
TTD: "TT",
XOF: "SN",
XAF: "CM",
XPF: "PF",
GHS: "GH",
UGX: "UG",
TZS: "TZ",
RWF: "RW",
ETB: "ET",
DZD: "DZ",
TND: "TN",
LYD: "LY",
LBP: "LB",
SYP: "SY",
IQD: "IQ",
IRR: "IR",
AFN: "AF",
YER: "YE",
AMD: "AM",
AZN: "AZ",
BYN: "BY",
GEL: "GE",
MDL: "MD",
KGS: "KG",
UZS: "UZ",
TMT: "TM",
MNT: "MN",
MMK: "MM",
LAK: "LA",
KHR: "KH",
BND: "BN",
PGK: "PG",
FJD: "FJ"
}
@country_names %{
"US" => "United States",
"CA" => "Canada",
"EU" => "European Union",
"GB" => "United Kingdom",
"JP" => "Japan",
"CH" => "Switzerland",
"AU" => "Australia",
"NZ" => "New Zealand",
"CN" => "China",
"HK" => "Hong Kong",
"SG" => "Singapore",
"KR" => "South Korea",
"IN" => "India",
"BR" => "Brazil",
"MX" => "Mexico",
"ZA" => "South Africa",
"SE" => "Sweden",
"NO" => "Norway",
"DK" => "Denmark",
"PL" => "Poland",
"CZ" => "Czechia",
"HU" => "Hungary",
"RO" => "Romania",
"TR" => "Türkiye",
"RU" => "Russia",
"IL" => "Israel",
"AE" => "United Arab Emirates",
"SA" => "Saudi Arabia",
"EG" => "Egypt",
"TH" => "Thailand",
"ID" => "Indonesia",
"PH" => "Philippines",
"MY" => "Malaysia",
"VN" => "Vietnam",
"TW" => "Taiwan",
"UA" => "Ukraine",
"AR" => "Argentina",
"CO" => "Colombia",
"PE" => "Peru",
"CL" => "Chile",
"PK" => "Pakistan",
"BD" => "Bangladesh",
"NG" => "Nigeria",
"KE" => "Kenya",
"KZ" => "Kazakhstan",
"MA" => "Morocco",
"BH" => "Bahrain",
"KW" => "Kuwait"
}
@doc "Returns a Unicode flag glyph for a currency code, or a neutral fallback."
@spec flag_for(atom() | String.t()) :: String.t()
def flag_for(code) when is_atom(code) do
case Map.get(@currency_to_territory, code) do
nil -> "🏳"
"EU" -> "🇪🇺"
territory -> territory_flag(territory)
end
end
def flag_for(code) when is_binary(code) do
try do
flag_for(String.to_existing_atom(code))
rescue
ArgumentError -> "🏳"
end
end
@doc "Returns a primary country/territory name for a currency code."
@spec country_for(atom() | String.t()) :: String.t() | nil
def country_for(code) when is_atom(code) do
case Map.get(@currency_to_territory, code) do
nil -> nil
territory -> Map.get(@country_names, territory, territory)
end
end
def country_for(_), do: nil
# Build the flag emoji from a 2-letter ISO 3166-1 alpha-2 code by
# pairing each ASCII letter with U+1F1E6 (regional indicator A).
defp territory_flag(<<a::utf8, b::utf8>>) when a in ?A..?Z and b in ?A..?Z do
<<a - ?A + 0x1F1E6::utf8, b - ?A + 0x1F1E6::utf8>>
end
defp territory_flag(_), do: "🏳"
end