from dataclasses import dataclass
import enum


def _flag_to_iso(flag: str) -> str:
    return "".join(
        chr(ord(c) - 0x1F1E6 + ord("A"))
        for c in flag
    )


def _iso_to_flag(iso: str) -> str:
    return "".join(
        chr(ord("🇦") + ord(c) - ord("A"))
        for c in iso.upper()
    )


@dataclass(frozen=True, order=True)
class _Country:
    id: int
    iso: str
    label: str

    @property
    def flag(self) -> str:
        return _iso_to_flag(self.iso)

    def __str__(self) -> str:
        return self.label


class Country(_Country, enum.Enum):
    AF =   1, "AF", "Afghanistan"
    AL =   2, "AL", "Albania"
    DZ =   3, "DZ", "Algeria"
    AS =   4, "AS", "American Samoa"
    AD =   5, "AD", "Andorra"
    AO =   6, "AO", "Angola"
    AI =   7, "AI", "Anguilla"
    AQ =   8, "AQ", "Antarctica"
    AG =   9, "AG", "Antigua and Barbuda"
    AR =  10, "AR", "Argentina"
    AM =  11, "AM", "Armenia"
    AW =  12, "AW", "Aruba"
    AU =  13, "AU", "Australia"
    AT =  14, "AT", "Austria"
    AZ =  15, "AZ", "Azerbaijan"
    BS =  16, "BS", "Bahamas"
    BH =  17, "BH", "Bahrain"
    BD =  18, "BD", "Bangladesh"
    BB =  19, "BB", "Barbados"
    BY =  20, "BY", "Belarus"
    BE =  21, "BE", "Belgium"
    BZ =  22, "BZ", "Belize"
    BJ =  23, "BJ", "Benin"
    BM =  24, "BM", "Bermuda"
    BT =  25, "BT", "Bhutan"
    BO =  26, "BO", "Bolivia"
    BQ =  27, "BQ", "Bonaire"
    BA =  28, "BA", "Bosnia and Herzegovina"
    BW =  29, "BW", "Botswana"
    BV =  30, "BV", "Bouvet Island"
    BR =  31, "BR", "Brazil"
    IO =  32, "IO", "British Indian Ocean Territory"
    BN =  33, "BN", "Brunei Darussalam"
    BG =  34, "BG", "Bulgaria"
    BF =  35, "BF", "Burkina Faso"
    BI =  36, "BI", "Burundi"
    CV =  37, "CV", "Cabo Verde"
    KH =  38, "KH", "Cambodia"
    CM =  39, "CM", "Cameroon"
    CA =  40, "CA", "Canada"
    KY =  41, "KY", "Cayman Islands"
    CF =  42, "CF", "Central African Republic"
    TD =  43, "TD", "Chad"
    CL =  44, "CL", "Chile"
    CN =  45, "CN", "China"
    CX =  46, "CX", "Christmas Island"
    CC =  47, "CC", "Cocos (Keeling) Islands"
    CO =  48, "CO", "Colombia"
    KM =  49, "KM", "Comoros"
    CG =  50, "CG", "Congo"
    CK =  51, "CK", "Cook Islands"
    CR =  52, "CR", "Costa Rica"
    HR =  53, "HR", "Croatia"
    CU =  54, "CU", "Cuba"
    CW =  55, "CW", "Curaçao"
    CY =  56, "CY", "Cyprus"
    CZ =  57, "CZ", "Czechia"
    CI =  58, "CI", "Côte d'Ivoire"
    DK =  59, "DK", "Denmark"
    DJ =  60, "DJ", "Djibouti"
    DM =  61, "DM", "Dominica"
    DO =  62, "DO", "Dominican Republic"
    EC =  63, "EC", "Ecuador"
    EG =  64, "EG", "Egypt"
    SV =  65, "SV", "El Salvador"
    GQ =  66, "GQ", "Equatorial Guinea"
    ER =  67, "ER", "Eritrea"
    EE =  68, "EE", "Estonia"
    SZ =  69, "SZ", "Eswatini"
    ET =  70, "ET", "Ethiopia"
    FK =  71, "FK", "Falkland Islands (Malvinas)"
    FO =  72, "FO", "Faroe Islands"
    FJ =  73, "FJ", "Fiji"
    FI =  74, "FI", "Finland"
    FR =  75, "FR", "France"
    GF =  76, "GF", "French Guiana"
    PF =  77, "PF", "French Polynesia"
    TF =  78, "TF", "French Southern Territories"
    GA =  79, "GA", "Gabon"
    GM =  80, "GM", "Gambia"
    GE =  81, "GE", "Georgia"
    DE =  82, "DE", "Germany"
    GH =  83, "GH", "Ghana"
    GI =  84, "GI", "Gibraltar"
    GR =  85, "GR", "Greece"
    GL =  86, "GL", "Greenland"
    GD =  87, "GD", "Grenada"
    GP =  88, "GP", "Guadeloupe"
    GU =  89, "GU", "Guam"
    GT =  90, "GT", "Guatemala"
    GG =  91, "GG", "Guernsey"
    GN =  92, "GN", "Guinea"
    GW =  93, "GW", "Guinea-Bissau"
    GY =  94, "GY", "Guyana"
    HT =  95, "HT", "Haiti"
    HM =  96, "HM", "Heard Island and McDonald Islands"
    HN =  97, "HN", "Honduras"
    HK =  98, "HK", "Hong Kong"
    HU =  99, "HU", "Hungary"
    IS = 100, "IS", "Iceland"
    IN = 101, "IN", "India"
    ID = 102, "ID", "Indonesia"
    IR = 103, "IR", "Iran"
    IQ = 104, "IQ", "Iraq"
    IE = 105, "IE", "Ireland"
    IM = 106, "IM", "Isle of Man"
    IL = 107, "IL", "Israel"
    IT = 108, "IT", "Italy"
    JM = 109, "JM", "Jamaica"
    JP = 110, "JP", "Japan"
    JE = 111, "JE", "Jersey"
    JO = 112, "JO", "Jordan"
    KZ = 113, "KZ", "Kazakhstan"
    KE = 114, "KE", "Kenya"
    KI = 115, "KI", "Kiribati"
    XK = 116, "XK", "Kosovo"
    KW = 117, "KW", "Kuwait"
    KG = 118, "KG", "Kyrgyzstan"
    LA = 119, "LA", "Laos"
    LV = 120, "LV", "Latvia"
    LB = 121, "LB", "Lebanon"
    LS = 122, "LS", "Lesotho"
    LR = 123, "LR", "Liberia"
    LY = 124, "LY", "Libya"
    LI = 125, "LI", "Liechtenstein"
    LT = 126, "LT", "Lithuania"
    LU = 127, "LU", "Luxembourg"
    MO = 128, "MO", "Macao"
    MG = 129, "MG", "Madagascar"
    MW = 130, "MW", "Malawi"
    MY = 131, "MY", "Malaysia"
    MV = 132, "MV", "Maldives"
    ML = 133, "ML", "Mali"
    MT = 134, "MT", "Malta"
    MH = 135, "MH", "Marshall Islands"
    MQ = 136, "MQ", "Martinique"
    MR = 137, "MR", "Mauritania"
    MU = 138, "MU", "Mauritius"
    YT = 139, "YT", "Mayotte"
    MX = 140, "MX", "Mexico"
    FM = 141, "FM", "Micronesia"
    MD = 142, "MD", "Moldova"
    MC = 143, "MC", "Monaco"
    MN = 144, "MN", "Mongolia"
    ME = 145, "ME", "Montenegro"
    MS = 146, "MS", "Montserrat"
    MA = 147, "MA", "Morocco"
    MZ = 148, "MZ", "Mozambique"
    MM = 149, "MM", "Myanmar"
    NA = 150, "NA", "Namibia"
    NR = 151, "NR", "Nauru"
    NP = 152, "NP", "Nepal"
    NL = 153, "NL", "Netherlands"
    NC = 154, "NC", "New Caledonia"
    NZ = 155, "NZ", "New Zealand"
    NI = 156, "NI", "Nicaragua"
    NE = 157, "NE", "Niger"
    NG = 158, "NG", "Nigeria"
    NU = 159, "NU", "Niue"
    NF = 160, "NF", "Norfolk Island"
    KP = 161, "KP", "North Korea"
    MK = 162, "MK", "North Macedonia"
    MP = 163, "MP", "Northern Mariana Islands"
    NO = 164, "NO", "Norway"
    OM = 165, "OM", "Oman"
    PK = 166, "PK", "Pakistan"
    PW = 167, "PW", "Palau"
    PS = 168, "PS", "Palestine"
    PA = 169, "PA", "Panama"
    PG = 170, "PG", "Papua New Guinea"
    PY = 171, "PY", "Paraguay"
    PE = 172, "PE", "Peru"
    PH = 173, "PH", "Philippines"
    PN = 174, "PN", "Pitcairn"
    PL = 175, "PL", "Poland"
    PT = 176, "PT", "Portugal"
    PR = 177, "PR", "Puerto Rico"
    QA = 178, "QA", "Qatar"
    CD = 179, "CD", "Republic of the Congo"
    RO = 180, "RO", "Romania"
    RU = 181, "RU", "Russia"
    RW = 182, "RW", "Rwanda"
    RE = 183, "RE", "Réunion"
    BL = 184, "BL", "Saint Barthélemy"
    SH = 185, "SH", "Saint Helena"
    KN = 186, "KN", "Saint Kitts and Nevis"
    LC = 187, "LC", "Saint Lucia"
    MF = 188, "MF", "Saint Martin (French part)"
    PM = 189, "PM", "Saint Pierre and Miquelon"
    VC = 190, "VC", "Saint Vincent and the Grenadines"
    WS = 191, "WS", "Samoa"
    SM = 192, "SM", "San Marino"
    ST = 193, "ST", "Sao Tome and Principe"
    SA = 194, "SA", "Saudi Arabia"
    SN = 195, "SN", "Senegal"
    RS = 196, "RS", "Serbia"
    SC = 197, "SC", "Seychelles"
    SL = 198, "SL", "Sierra Leone"
    SG = 199, "SG", "Singapore"
    SX = 200, "SX", "Sint Maarten (Dutch part)"
    SK = 201, "SK", "Slovakia"
    SI = 202, "SI", "Slovenia"
    SB = 203, "SB", "Solomon Islands"
    SO = 204, "SO", "Somalia"
    ZA = 205, "ZA", "South Africa"
    GS = 206, "GS", "South Georgia and the South Sandwich Islands"
    KR = 207, "KR", "South Korea"
    SS = 208, "SS", "South Sudan"
    ES = 209, "ES", "Spain"
    LK = 210, "LK", "Sri Lanka"
    SD = 211, "SD", "Sudan"
    SR = 212, "SR", "Suriname"
    SJ = 213, "SJ", "Svalbard and Jan Mayen"
    SE = 214, "SE", "Sweden"
    CH = 215, "CH", "Switzerland"
    SY = 216, "SY", "Syrian Arab Republic"
    TW = 217, "TW", "Taiwan"
    TJ = 218, "TJ", "Tajikistan"
    TZ = 219, "TZ", "Tanzania"
    TH = 220, "TH", "Thailand"
    TL = 221, "TL", "Timor-Leste"
    TG = 222, "TG", "Togo"
    TK = 223, "TK", "Tokelau"
    TO = 224, "TO", "Tonga"
    TT = 225, "TT", "Trinidad and Tobago"
    TN = 226, "TN", "Tunisia"
    TM = 227, "TM", "Turkmenistan"
    TC = 228, "TC", "Turks and Caicos Islands"
    TV = 229, "TV", "Tuvalu"
    TR = 230, "TR", "Türkiye"
    UG = 231, "UG", "Uganda"
    UA = 232, "UA", "Ukraine"
    AE = 233, "AE", "United Arab Emirates"
    GB = 234, "GB", "United Kingdom"
    US = 235, "US", "United States"
    UM = 236, "UM", "United States Minor Outlying Islands"
    UY = 237, "UY", "Uruguay"
    UZ = 238, "UZ", "Uzbekistan"
    VU = 239, "VU", "Vanuatu"
    VA = 240, "VA", "Vatican City"
    VE = 241, "VE", "Venezuela"
    VN = 242, "VN", "Viet Nam"
    VG = 243, "VG", "Virgin Islands"
    VI = 244, "VI", "Virgin Islands"
    WF = 245, "WF", "Wallis and Futuna"
    EH = 246, "EH", "Western Sahara"
    YE = 247, "YE", "Yemen"
    ZM = 248, "ZM", "Zambia"
    ZW = 249, "ZW", "Zimbabwe"
    AX = 250, "AX", "Åland Islands"
    IC = 251, "IC", "Canary Islands"


_ID_MAP: dict[int, Country] = {c.id: c for c in Country}
_ISO_MAP: dict[str, Country] = {c.iso: c for c in Country}
_FLAG_MAP: dict[str, Country] = {c.flag: c for c in Country}


def from_id(id: int) -> Country:
    return _ID_MAP[id]


def from_iso(iso: str) -> Country:
    return _ISO_MAP[iso]


def from_flag(flag: str) -> Country:
    return _FLAG_MAP[flag]
