/*
 *  Copyright (C) 2025 Team Kodi
 *  This file is part of Kodi - https://kodi.tv
 *
 *  SPDX-License-Identifier: GPL-2.0-or-later
 *  See LICENSES/README.md for more information.
 */

#pragma once

#include "utils/StringUtils.h"

#include <algorithm>
#include <array>
#include <string_view>

namespace KODI::UTILS::I18N
{
struct ISO3166_1
{
  std::string_view alpha2; // alpha-2 code
  std::string_view alpha3; // alpha-3 code
  std::string_view name; // English name
};

// ISO 3166-1 table
// Source: ISO https://www.iso.org/iso-3166-country-codes.html, sorted by alpha-2

// 242 officially assigned + 7 reassigned codes
inline constexpr int ISO3166_1_COUNT = 249;

//! @todo handle "transitionally reserved" codes, maybe remap them? an bu cs nt tp yu zr
//! @todo handle reassigned codes differently? ai bq ge lt me ru sk

// clang-format off
inline constexpr std::array<ISO3166_1, ISO3166_1_COUNT> TableISO3166_1 = {{
   {"ad", "and", "Andorra"},
   {"ae", "are", "United Arab Emirates (the)"},
   {"af", "afg", "Afghanistan"},
   {"ag", "atg", "Antigua and Barbuda"},
   {"ai", "aia", "Anguilla"},
   {"al", "alb", "Albania"},
   {"am", "arm", "Armenia"},
   {"ao", "ago", "Angola"},
   {"aq", "ata", "Antarctica"},
   {"ar", "arg", "Argentina"},
   {"as", "asm", "American Samoa"},
   {"at", "aut", "Austria"},
   {"au", "aus", "Australia"},
   {"aw", "abw", "Aruba"},
   {"ax", "ala", "Åland Islands"},
   {"az", "aze", "Azerbaijan"},
   {"ba", "bih", "Bosnia and Herzegovina"},
   {"bb", "brb", "Barbados"},
   {"bd", "bgd", "Bangladesh"},
   {"be", "bel", "Belgium"},
   {"bf", "bfa", "Burkina Faso"},
   {"bg", "bgr", "Bulgaria"},
   {"bh", "bhr", "Bahrain"},
   {"bi", "bdi", "Burundi"},
   {"bj", "ben", "Benin"},
   {"bl", "blm", "Saint Barthélemy"},
   {"bm", "bmu", "Bermuda"},
   {"bn", "brn", "Brunei Darussalam"},
   {"bo", "bol", "Bolivia (Plurinational State of)"},
   {"bq", "bes", "Bonaire, Sint Eustatius and Saba"},
   {"br", "bra", "Brazil"},
   {"bs", "bhs", "Bahamas (the)"},
   {"bt", "btn", "Bhutan"},
   {"bv", "bvt", "Bouvet Island"},
   {"bw", "bwa", "Botswana"},
   {"by", "blr", "Belarus"},
   {"bz", "blz", "Belize"},
   {"ca", "can", "Canada"},
   {"cc", "cck", "Cocos (Keeling) Islands (the)"},
   {"cd", "cod", "Congo (the Democratic Republic of the)"},
   {"cf", "caf", "Central African Republic (the)"},
   {"cg", "cog", "Congo (the)"},
   {"ch", "che", "Switzerland"},
   {"ci", "civ", "Côte d'Ivoire"},
   {"ck", "cok", "Cook Islands (the)"},
   {"cl", "chl", "Chile"},
   {"cm", "cmr", "Cameroon"},
   {"cn", "chn", "China"},
   {"co", "col", "Colombia"},
   {"cr", "cri", "Costa Rica"},
   {"cu", "cub", "Cuba"},
   {"cv", "cpv", "Cabo Verde"},
   {"cw", "cuw", "Curaçao"},
   {"cx", "cxr", "Christmas Island"},
   {"cy", "cyp", "Cyprus"},
   {"cz", "cze", "Czechia"},
   {"de", "deu", "Germany"},
   {"dj", "dji", "Djibouti"},
   {"dk", "dnk", "Denmark"},
   {"dm", "dma", "Dominica"},
   {"do", "dom", "Dominican Republic (the)"},
   {"dz", "dza", "Algeria"},
   {"ec", "ecu", "Ecuador"},
   {"ee", "est", "Estonia"},
   {"eg", "egy", "Egypt"},
   {"eh", "esh", "Western Sahara"},
   {"er", "eri", "Eritrea"},
   {"es", "esp", "Spain"},
   {"et", "eth", "Ethiopia"},
   {"fi", "fin", "Finland"},
   {"fj", "fji", "Fiji"},
   {"fk", "flk", "Falkland Islands (the) [Malvinas]"},
   {"fm", "fsm", "Micronesia (Federated States of)"},
   {"fo", "fro", "Faroe Islands (the)"},
   {"fr", "fra", "France"},
   {"ga", "gab", "Gabon"},
   {"gb", "gbr", "United Kingdom of Great Britain and Northern Ireland (the)"},
   {"gd", "grd", "Grenada"},
   {"ge", "geo", "Georgia"},
   {"gf", "guf", "French Guiana"},
   {"gg", "ggy", "Guernsey"},
   {"gh", "gha", "Ghana"},
   {"gi", "gib", "Gibraltar"},
   {"gl", "grl", "Greenland"},
   {"gm", "gmb", "Gambia (the)"},
   {"gn", "gin", "Guinea"},
   {"gp", "glp", "Guadeloupe"},
   {"gq", "gnq", "Equatorial Guinea"},
   {"gr", "grc", "Greece"},
   {"gs", "sgs", "South Georgia and the South Sandwich Islands"},
   {"gt", "gtm", "Guatemala"},
   {"gu", "gum", "Guam"},
   {"gw", "gnb", "Guinea-Bissau"},
   {"gy", "guy", "Guyana"},
   {"hk", "hkg", "Hong Kong"},
   {"hm", "hmd", "Heard Island and McDonald Islands"},
   {"hn", "hnd", "Honduras"},
   {"hr", "hrv", "Croatia"},
   {"ht", "hti", "Haiti"},
   {"hu", "hun", "Hungary"},
   {"id", "idn", "Indonesia"},
   {"ie", "irl", "Ireland"},
   {"il", "isr", "Israel"},
   {"im", "imn", "Isle of Man"},
   {"in", "ind", "India"},
   {"io", "iot", "British Indian Ocean Territory (the)"},
   {"iq", "irq", "Iraq"},
   {"ir", "irn", "Iran (Islamic Republic of)"},
   {"is", "isl", "Iceland"},
   {"it", "ita", "Italy"},
   {"je", "jey", "Jersey"},
   {"jm", "jam", "Jamaica"},
   {"jo", "jor", "Jordan"},
   {"jp", "jpn", "Japan"},
   {"ke", "ken", "Kenya"},
   {"kg", "kgz", "Kyrgyzstan"},
   {"kh", "khm", "Cambodia"},
   {"ki", "kir", "Kiribati"},
   {"km", "com", "Comoros (the)"},
   {"kn", "kna", "Saint Kitts and Nevis"},
   {"kp", "prk", "Korea (the Democratic People's Republic of)"},
   {"kr", "kor", "Korea (the Republic of)"},
   {"kw", "kwt", "Kuwait"},
   {"ky", "cym", "Cayman Islands (the)"},
   {"kz", "kaz", "Kazakhstan"},
   {"la", "lao", "Lao People's Democratic Republic (the)"},
   {"lb", "lbn", "Lebanon"},
   {"lc", "lca", "Saint Lucia"},
   {"li", "lie", "Liechtenstein"},
   {"lk", "lka", "Sri Lanka"},
   {"lr", "lbr", "Liberia"},
   {"ls", "lso", "Lesotho"},
   {"lt", "ltu", "Lithuania"},
   {"lu", "lux", "Luxembourg"},
   {"lv", "lva", "Latvia"},
   {"ly", "lby", "Libya"},
   {"ma", "mar", "Morocco"},
   {"mc", "mco", "Monaco"},
   {"md", "mda", "Moldova (the Republic of)"},
   {"me", "mne", "Montenegro"},
   {"mf", "maf", "Saint Martin (French part)"},
   {"mg", "mdg", "Madagascar"},
   {"mh", "mhl", "Marshall Islands (the)"},
   {"mk", "mkd", "Republic of North Macedonia"},
   {"ml", "mli", "Mali"},
   {"mm", "mmr", "Myanmar"},
   {"mn", "mng", "Mongolia"},
   {"mo", "mac", "Macao"},
   {"mp", "mnp", "Northern Mariana Islands (the)"},
   {"mq", "mtq", "Martinique"},
   {"mr", "mrt", "Mauritania"},
   {"ms", "msr", "Montserrat"},
   {"mt", "mlt", "Malta"},
   {"mu", "mus", "Mauritius"},
   {"mv", "mdv", "Maldives"},
   {"mw", "mwi", "Malawi"},
   {"mx", "mex", "Mexico"},
   {"my", "mys", "Malaysia"},
   {"mz", "moz", "Mozambique"},
   {"na", "nam", "Namibia"},
   {"nc", "ncl", "New Caledonia"},
   {"ne", "ner", "Niger (the)"},
   {"nf", "nfk", "Norfolk Island"},
   {"ng", "nga", "Nigeria"},
   {"ni", "nic", "Nicaragua"},
   {"nl", "nld", "Netherlands (the)"},
   {"no", "nor", "Norway"},
   {"np", "npl", "Nepal"},
   {"nr", "nru", "Nauru"},
   {"nu", "niu", "Niue"},
   {"nz", "nzl", "New Zealand"},
   {"om", "omn", "Oman"},
   {"pa", "pan", "Panama"},
   {"pe", "per", "Peru"},
   {"pf", "pyf", "French Polynesia"},
   {"pg", "png", "Papua New Guinea"},
   {"ph", "phl", "Philippines (the)"},
   {"pk", "pak", "Pakistan"},
   {"pl", "pol", "Poland"},
   {"pm", "spm", "Saint Pierre and Miquelon"},
   {"pn", "pcn", "Pitcairn"},
   {"pr", "pri", "Puerto Rico"},
   {"ps", "pse", "Palestine, State of"},
   {"pt", "prt", "Portugal"},
   {"pw", "plw", "Palau"},
   {"py", "pry", "Paraguay"},
   {"qa", "qat", "Qatar"},
   {"re", "reu", "Réunion"},
   {"ro", "rou", "Romania"},
   {"rs", "srb", "Serbia"},
   {"ru", "rus", "Russian Federation (the)"},
   {"rw", "rwa", "Rwanda"},
   {"sa", "sau", "Saudi Arabia"},
   {"sb", "slb", "Solomon Islands"},
   {"sc", "syc", "Seychelles"},
   {"sd", "sdn", "Sudan (the)"},
   {"se", "swe", "Sweden"},
   {"sg", "sgp", "Singapore"},
   {"sh", "shn", "Saint Helena, Ascension and Tristan da Cunha"},
   {"si", "svn", "Slovenia"},
   {"sj", "sjm", "Svalbard and Jan Mayen"},
   {"sk", "svk", "Slovakia"},
   {"sl", "sle", "Sierra Leone"},
   {"sm", "smr", "San Marino"},
   {"sn", "sen", "Senegal"},
   {"so", "som", "Somalia"},
   {"sr", "sur", "Suriname"},
   {"ss", "ssd", "South Sudan"},
   {"st", "stp", "Sao Tome and Principe"},
   {"sv", "slv", "El Salvador"},
   {"sx", "sxm", "Sint Maarten (Dutch part)"},
   {"sy", "syr", "Syrian Arab Republic"},
   {"sz", "swz", "Eswatini"},
   {"tc", "tca", "Turks and Caicos Islands (the)"},
   {"td", "tcd", "Chad"},
   {"tf", "atf", "French Southern Territories (the)"},
   {"tg", "tgo", "Togo"},
   {"th", "tha", "Thailand"},
   {"tj", "tjk", "Tajikistan"},
   {"tk", "tkl", "Tokelau"},
   {"tl", "tls", "Timor-Leste"},
   {"tm", "tkm", "Turkmenistan"},
   {"tn", "tun", "Tunisia"},
   {"to", "ton", "Tonga"},
   {"tr", "tur", "Turkey"},
   {"tt", "tto", "Trinidad and Tobago"},
   {"tv", "tuv", "Tuvalu"},
   {"tw", "twn", "Taiwan (Province of China)"},
   {"tz", "tza", "Tanzania, United Republic of"},
   {"ua", "ukr", "Ukraine"},
   {"ug", "uga", "Uganda"},
   {"um", "umi", "United States Minor Outlying Islands (the)"},
   {"us", "usa", "United States of America (the)"},
   {"uy", "ury", "Uruguay"},
   {"uz", "uzb", "Uzbekistan"},
   {"va", "vat", "Holy See (the)"},
   {"vc", "vct", "Saint Vincent and the Grenadines"},
   {"ve", "ven", "Venezuela (Bolivarian Republic of)"},
   {"vg", "vgb", "Virgin Islands (British)"},
   {"vi", "vir", "Virgin Islands (U.S.)"},
   {"vn", "vnm", "Viet Nam"},
   {"vu", "vut", "Vanuatu"},
   {"wf", "wlf", "Wallis and Futuna"},
   {"ws", "wsm", "Samoa"},
   {"ye", "yem", "Yemen"},
   {"yt", "myt", "Mayotte"},
   {"za", "zaf", "South Africa"},
   {"zm", "zmb", "Zambia"},
   {"zw", "zwe", "Zimbabwe"}
}};
// clang-format on

static_assert(std::ranges::is_sorted(TableISO3166_1, {}, &ISO3166_1::alpha2));

static_assert(std::ranges::all_of(
    TableISO3166_1,
    [](std::string_view name) { return StringUtils::IsAsciiTrimmed(name); },
    &ISO3166_1::name));

constexpr auto CreateTableISO3166_1ByAlpha3()
{
  auto codes{TableISO3166_1};
  std::ranges::sort(codes, {}, &ISO3166_1::alpha3);
  return codes;
}

inline constexpr auto TableISO3166_1ByAlpha3 = CreateTableISO3166_1ByAlpha3();

//-------------------------------------------------------------------------------------------------
// Data integrity validations
//

static_assert(std::ranges::adjacent_find(TableISO3166_1, {}, &ISO3166_1::alpha2) ==
              TableISO3166_1.end());

static_assert(std::ranges::adjacent_find(TableISO3166_1ByAlpha3, {}, &ISO3166_1::alpha3) ==
              TableISO3166_1ByAlpha3.end());

} // namespace KODI::UTILS::I18N
