lib/code_converter.ex

defmodule CountryCodeConverter do
  @moduledoc """
  CountryCodeConverter is a module for converting iso2 / iso3 / ioc country codes.

  It can get a country codes for some particular iso code:

      iex> {:ok, countries} = CountryCodeConverter.countries(:iso2)
      iex> Enum.member?(countries, "BR")
      true

  You can also convert one code to another:

      iex> CountryCodeConverter.convert(:iso2, "BR")
      {:ok, %{iso2: "BR", iso3: "BRA", ioc: "BRA"}}

  """

  @iso2 %{
    "TW" => {"TPE", "TWN"},
    "AF" => {"AFG", "AFG"},
    "AL" => {"ALB", "ALB"},
    "DZ" => {"ALG", "DZA"},
    "AS" => {"ASA", "ASM"},
    "AD" => {"AND", "AND"},
    "AO" => {"ANG", "AGO"},
    "AI" => {"AIA", "AIA"},
    "AQ" => {nil, "ATA"},
    "AG" => {"ANT", "ATG"},
    "AR" => {"ARG", "ARG"},
    "AM" => {"ARM", "ARM"},
    "AW" => {"ARU", "ABW"},
    "AU" => {"AUS", "AUS"},
    "AT" => {"AUT", "AUT"},
    "AZ" => {"AZE", "AZE"},
    "BS" => {"BAH", "BHS"},
    "BH" => {"BRN", "BHR"},
    "BD" => {"BAN", "BGD"},
    "BB" => {"BAR", "BRB"},
    "BY" => {"BLR", "BLR"},
    "BE" => {"BEL", "BEL"},
    "BZ" => {"BIZ", "BLZ"},
    "BJ" => {"BEN", "BEN"},
    "BM" => {"BER", "BMU"},
    "BT" => {"BHU", "BTN"},
    "BO" => {"BOL", "BOL"},
    "BQ" => {"AHO", "BES"},
    "BA" => {"BIH", "BIH"},
    "BW" => {"BOT", "BWA"},
    "BV" => {nil, "BVT"},
    "BR" => {"BRA", "BRA"},
    "IO" => {nil, "IOT"},
    "VG" => {"IVB", "VGB"},
    "BN" => {"BRU", "BRN"},
    "BG" => {"BUL", "BGR"},
    "BF" => {"BUR", "BFA"},
    "BI" => {"BDI", "BDI"},
    "CV" => {"CPV", "CPV"},
    "KH" => {"CAM", "KHM"},
    "CM" => {"CMR", "CMR"},
    "CA" => {"CAN", "CAN"},
    "KY" => {"CAY", "CYM"},
    "CF" => {"CAF", "CAF"},
    "TD" => {"CHA", "TCD"},
    "CL" => {"CHI", "CHL"},
    "CN" => {"CHN", "CHN"},
    "HK" => {"HKG", "HKG"},
    "MO" => {"MAC", "MAC"},
    "CX" => {nil, "CXR"},
    "CC" => {nil, "CCK"},
    "CO" => {"COL", "COL"},
    "KM" => {"COM", "COM"},
    "CG" => {"CGO", "COG"},
    "CK" => {"COK", "COK"},
    "CR" => {"CRC", "CRI"},
    "HR" => {"CRO", "HRV"},
    "CU" => {"CUB", "CUB"},
    "CW" => {nil, "CUW"},
    "CY" => {"CYP", "CYP"},
    "CZ" => {"CZE", "CZE"},
    "CI" => {"CIV", "CIV"},
    "KP" => {"PRK", "PRK"},
    "CD" => {"COD", "COD"},
    "DK" => {"DEN", "DNK"},
    "DJ" => {"DJI", "DJI"},
    "DM" => {"DMA", "DMA"},
    "DO" => {"DOM", "DOM"},
    "EC" => {"ECU", "ECU"},
    "EG" => {"EGY", "EGY"},
    "SV" => {"ESA", "SLV"},
    "GQ" => {"GEQ", "GNQ"},
    "ER" => {"ERI", "ERI"},
    "EE" => {"EST", "EST"},
    "ET" => {"ETH", "ETH"},
    "FK" => {"FLK", "FLK"},
    "FO" => {"FAR", "FRO"},
    "FJ" => {"FIJ", "FJI"},
    "FI" => {"FIN", "FIN"},
    "FR" => {"FRA", "FRA"},
    "GF" => {"FGU", "GUF"},
    "PF" => {"FPO", "PYF"},
    "TF" => {nil, "ATF"},
    "GA" => {"GAB", "GAB"},
    "GM" => {"GAM", "GMB"},
    "GE" => {"GEO", "GEO"},
    "DE" => {"GER", "DEU"},
    "GH" => {"GHA", "GHA"},
    "GI" => {"GIB", "GIB"},
    "GR" => {"GRE", "GRC"},
    "GL" => {"GRL", "GRL"},
    "GD" => {"GRN", "GRD"},
    "GP" => {"GUD", "GLP"},
    "GU" => {"GUM", "GUM"},
    "GT" => {"GUA", "GTM"},
    "GG" => {nil, "GGY"},
    "GN" => {"GUI", "GIN"},
    "GW" => {"GBS", "GNB"},
    "GY" => {"GUY", "GUY"},
    "HT" => {"HAI", "HTI"},
    "HM" => {nil, "HMD"},
    "VA" => {nil, "VAT"},
    "HN" => {"HON", "HND"},
    "HU" => {"HUN", "HUN"},
    "IS" => {"ISL", "ISL"},
    "IN" => {"IND", "IND"},
    "ID" => {"INA", "IDN"},
    "IR" => {"IRI", "IRN"},
    "IQ" => {"IRQ", "IRQ"},
    "IE" => {"IRL", "IRL"},
    "IM" => {nil, "IMN"},
    "IL" => {"ISR", "ISR"},
    "IT" => {"ITA", "ITA"},
    "JM" => {"JAM", "JAM"},
    "JP" => {"JPN", "JPN"},
    "JE" => {nil, "JEY"},
    "JO" => {"JOR", "JOR"},
    "KZ" => {"KAZ", "KAZ"},
    "KE" => {"KEN", "KEN"},
    "KI" => {"KIR", "KIR"},
    "KW" => {"KUW", "KWT"},
    "KG" => {"KGZ", "KGZ"},
    "LA" => {"LAO", "LAO"},
    "LV" => {"LAT", "LVA"},
    "LB" => {"LIB", "LBN"},
    "LS" => {"LES", "LSO"},
    "LR" => {"LBR", "LBR"},
    "LY" => {"LBA", "LBY"},
    "LI" => {"LIE", "LIE"},
    "LT" => {"LTU", "LTU"},
    "LU" => {"LUX", "LUX"},
    "MG" => {"MAD", "MDG"},
    "MW" => {"MAW", "MWI"},
    "MY" => {"MAS", "MYS"},
    "MV" => {"MDV", "MDV"},
    "ML" => {"MLI", "MLI"},
    "MT" => {"MLT", "MLT"},
    "MH" => {"MSH", "MHL"},
    "MQ" => {"MRT", "MTQ"},
    "MR" => {"MTN", "MRT"},
    "MU" => {"MRI", "MUS"},
    "YT" => {"MAY", "MYT"},
    "MX" => {"MEX", "MEX"},
    "FM" => {"FSM", "FSM"},
    "MC" => {"MON", "MCO"},
    "MN" => {"MGL", "MNG"},
    "ME" => {"MGO", "MNE"},
    "MS" => {"MNT", "MSR"},
    "MA" => {"MAR", "MAR"},
    "MZ" => {"MOZ", "MOZ"},
    "MM" => {"MYA", "MMR"},
    "NA" => {"NAM", "NAM"},
    "NR" => {"NRU", "NRU"},
    "NP" => {"NEP", "NPL"},
    "NL" => {"NED", "NLD"},
    "NC" => {"NCD", "NCL"},
    "NZ" => {"NZL", "NZL"},
    "NI" => {"NCA", "NIC"},
    "NE" => {"NIG", "NER"},
    "NG" => {"NGR", "NGA"},
    "NU" => {"NIU", "NIU"},
    "NF" => {"NFI", "NFK"},
    "MP" => {"NMA", "MNP"},
    "NO" => {"NOR", "NOR"},
    "OM" => {"OMA", "OMN"},
    "PK" => {"PAK", "PAK"},
    "PW" => {"PLW", "PLW"},
    "PA" => {"PAN", "PAN"},
    "PG" => {"PNG", "PNG"},
    "PY" => {"PAR", "PRY"},
    "PE" => {"PER", "PER"},
    "PH" => {"PHI", "PHL"},
    "PN" => {nil, "PCN"},
    "PL" => {"POL", "POL"},
    "PT" => {"POR", "PRT"},
    "PR" => {"PUR", "PRI"},
    "QA" => {"QAT", "QAT"},
    "KR" => {"KOR", "KOR"},
    "MD" => {"MDA", "MDA"},
    "RO" => {"ROU", "ROU"},
    "RU" => {"RUS", "RUS"},
    "RW" => {"RWA", "RWA"},
    "RE" => {"REU", "REU"},
    "BL" => {nil, "BLM"},
    "SH" => {"HEL", "SHN"},
    "KN" => {"SKN", "KNA"},
    "LC" => {"LCA", "LCA"},
    "MF" => {nil, "MAF"},
    "PM" => {"SPM", "SPM"},
    "VC" => {"VIN", "VCT"},
    "WS" => {"SAM", "WSM"},
    "SM" => {"SMR", "SMR"},
    "ST" => {"STP", "STP"},
    "SA" => {"KSA", "SAU"},
    "SN" => {"SEN", "SEN"},
    "RS" => {"SRB", "SRB"},
    "SC" => {"SEY", "SYC"},
    "SL" => {"SLE", "SLE"},
    "SG" => {"SIN", "SGP"},
    "SX" => {nil, "SXM"},
    "SK" => {"SVK", "SVK"},
    "SI" => {"SLO", "SVN"},
    "SB" => {"SOL", "SLB"},
    "SO" => {"SOM", "SOM"},
    "ZA" => {"RSA", "ZAF"},
    "GS" => {nil, "SGS"},
    "SS" => {nil, "SSD"},
    "ES" => {"ESP", "ESP"},
    "LK" => {"SRI", "LKA"},
    "PS" => {"PLE", "PSE"},
    "SD" => {"SUD", "SDN"},
    "SR" => {"SUR", "SUR"},
    "SJ" => {nil, "SJM"},
    "SZ" => {"SWZ", "SWZ"},
    "SE" => {"SWE", "SWE"},
    "CH" => {"SUI", "CHE"},
    "SY" => {"SYR", "SYR"},
    "TJ" => {"TJK", "TJK"},
    "TH" => {"THA", "THA"},
    "MK" => {"MKD", "MKD"},
    "TL" => {"TLS", "TLS"},
    "TG" => {"TOG", "TGO"},
    "TK" => {nil, "TKL"},
    "TO" => {"TGA", "TON"},
    "TT" => {"TTO", "TTO"},
    "TN" => {"TUN", "TUN"},
    "TR" => {"TUR", "TUR"},
    "TM" => {"TKM", "TKM"},
    "TC" => {"TKS", "TCA"},
    "TV" => {"TUV", "TUV"},
    "UG" => {"UGA", "UGA"},
    "UA" => {"UKR", "UKR"},
    "AE" => {"UAE", "ARE"},
    "GB" => {"GBR", "GBR"},
    "TZ" => {"TAN", "TZA"},
    "UM" => {nil, "UMI"},
    "VI" => {"ISV", "VIR"},
    "US" => {"USA", "USA"},
    "UY" => {"URU", "URY"},
    "UZ" => {"UZB", "UZB"},
    "VU" => {"VAN", "VUT"},
    "VE" => {"VEN", "VEN"},
    "VN" => {"VIE", "VNM"},
    "WF" => {"WAF", "WLF"},
    "EH" => {nil, "ESH"},
    "YE" => {"YEM", "YEM"},
    "ZM" => {"ZAM", "ZMB"},
    "ZW" => {"ZIM", "ZWE"},
    "AX" => {nil, "ALA"}
  }

  @iso3 %{
    "TWN" => {"TPE", "TW"},
    "AFG" => {"AFG", "AF"},
    "ALB" => {"ALB", "AL"},
    "DZA" => {"ALG", "DZ"},
    "ASM" => {"ASA", "AS"},
    "AND" => {"AND", "AD"},
    "AGO" => {"ANG", "AO"},
    "AIA" => {"AIA", "AI"},
    "ATA" => {nil, "AQ"},
    "ATG" => {"ANT", "AG"},
    "ARG" => {"ARG", "AR"},
    "ARM" => {"ARM", "AM"},
    "ABW" => {"ARU", "AW"},
    "AUS" => {"AUS", "AU"},
    "AUT" => {"AUT", "AT"},
    "AZE" => {"AZE", "AZ"},
    "BHS" => {"BAH", "BS"},
    "BHR" => {"BRN", "BH"},
    "BGD" => {"BAN", "BD"},
    "BRB" => {"BAR", "BB"},
    "BLR" => {"BLR", "BY"},
    "BEL" => {"BEL", "BE"},
    "BLZ" => {"BIZ", "BZ"},
    "BEN" => {"BEN", "BJ"},
    "BMU" => {"BER", "BM"},
    "BTN" => {"BHU", "BT"},
    "BOL" => {"BOL", "BO"},
    "BES" => {"AHO", "BQ"},
    "BIH" => {"BIH", "BA"},
    "BWA" => {"BOT", "BW"},
    "BVT" => {nil, "BV"},
    "BRA" => {"BRA", "BR"},
    "IOT" => {nil, "IO"},
    "VGB" => {"IVB", "VG"},
    "BRN" => {"BRU", "BN"},
    "BGR" => {"BUL", "BG"},
    "BFA" => {"BUR", "BF"},
    "BDI" => {"BDI", "BI"},
    "CPV" => {"CPV", "CV"},
    "KHM" => {"CAM", "KH"},
    "CMR" => {"CMR", "CM"},
    "CAN" => {"CAN", "CA"},
    "CYM" => {"CAY", "KY"},
    "CAF" => {"CAF", "CF"},
    "TCD" => {"CHA", "TD"},
    "CHL" => {"CHI", "CL"},
    "CHN" => {"CHN", "CN"},
    "HKG" => {"HKG", "HK"},
    "MAC" => {"MAC", "MO"},
    "CXR" => {nil, "CX"},
    "CCK" => {nil, "CC"},
    "COL" => {"COL", "CO"},
    "COM" => {"COM", "KM"},
    "COG" => {"CGO", "CG"},
    "COK" => {"COK", "CK"},
    "CRI" => {"CRC", "CR"},
    "HRV" => {"CRO", "HR"},
    "CUB" => {"CUB", "CU"},
    "CUW" => {nil, "CW"},
    "CYP" => {"CYP", "CY"},
    "CZE" => {"CZE", "CZ"},
    "CIV" => {"CIV", "CI"},
    "PRK" => {"PRK", "KP"},
    "COD" => {"COD", "CD"},
    "DNK" => {"DEN", "DK"},
    "DJI" => {"DJI", "DJ"},
    "DMA" => {"DMA", "DM"},
    "DOM" => {"DOM", "DO"},
    "ECU" => {"ECU", "EC"},
    "EGY" => {"EGY", "EG"},
    "SLV" => {"ESA", "SV"},
    "GNQ" => {"GEQ", "GQ"},
    "ERI" => {"ERI", "ER"},
    "EST" => {"EST", "EE"},
    "ETH" => {"ETH", "ET"},
    "FLK" => {"FLK", "FK"},
    "FRO" => {"FAR", "FO"},
    "FJI" => {"FIJ", "FJ"},
    "FIN" => {"FIN", "FI"},
    "FRA" => {"FRA", "FR"},
    "GUF" => {"FGU", "GF"},
    "PYF" => {"FPO", "PF"},
    "ATF" => {nil, "TF"},
    "GAB" => {"GAB", "GA"},
    "GMB" => {"GAM", "GM"},
    "GEO" => {"GEO", "GE"},
    "DEU" => {"GER", "DE"},
    "GHA" => {"GHA", "GH"},
    "GIB" => {"GIB", "GI"},
    "GRC" => {"GRE", "GR"},
    "GRL" => {"GRL", "GL"},
    "GRD" => {"GRN", "GD"},
    "GLP" => {"GUD", "GP"},
    "GUM" => {"GUM", "GU"},
    "GTM" => {"GUA", "GT"},
    "GGY" => {nil, "GG"},
    "GIN" => {"GUI", "GN"},
    "GNB" => {"GBS", "GW"},
    "GUY" => {"GUY", "GY"},
    "HTI" => {"HAI", "HT"},
    "HMD" => {nil, "HM"},
    "VAT" => {nil, "VA"},
    "HND" => {"HON", "HN"},
    "HUN" => {"HUN", "HU"},
    "ISL" => {"ISL", "IS"},
    "IND" => {"IND", "IN"},
    "IDN" => {"INA", "ID"},
    "IRN" => {"IRI", "IR"},
    "IRQ" => {"IRQ", "IQ"},
    "IRL" => {"IRL", "IE"},
    "IMN" => {nil, "IM"},
    "ISR" => {"ISR", "IL"},
    "ITA" => {"ITA", "IT"},
    "JAM" => {"JAM", "JM"},
    "JPN" => {"JPN", "JP"},
    "JEY" => {nil, "JE"},
    "JOR" => {"JOR", "JO"},
    "KAZ" => {"KAZ", "KZ"},
    "KEN" => {"KEN", "KE"},
    "KIR" => {"KIR", "KI"},
    "KWT" => {"KUW", "KW"},
    "KGZ" => {"KGZ", "KG"},
    "LAO" => {"LAO", "LA"},
    "LVA" => {"LAT", "LV"},
    "LBN" => {"LIB", "LB"},
    "LSO" => {"LES", "LS"},
    "LBR" => {"LBR", "LR"},
    "LBY" => {"LBA", "LY"},
    "LIE" => {"LIE", "LI"},
    "LTU" => {"LTU", "LT"},
    "LUX" => {"LUX", "LU"},
    "MDG" => {"MAD", "MG"},
    "MWI" => {"MAW", "MW"},
    "MYS" => {"MAS", "MY"},
    "MDV" => {"MDV", "MV"},
    "MLI" => {"MLI", "ML"},
    "MLT" => {"MLT", "MT"},
    "MHL" => {"MSH", "MH"},
    "MTQ" => {"MRT", "MQ"},
    "MRT" => {"MTN", "MR"},
    "MUS" => {"MRI", "MU"},
    "MYT" => {"MAY", "YT"},
    "MEX" => {"MEX", "MX"},
    "FSM" => {"FSM", "FM"},
    "MCO" => {"MON", "MC"},
    "MNG" => {"MGL", "MN"},
    "MNE" => {"MGO", "ME"},
    "MSR" => {"MNT", "MS"},
    "MAR" => {"MAR", "MA"},
    "MOZ" => {"MOZ", "MZ"},
    "MMR" => {"MYA", "MM"},
    "NAM" => {"NAM", "NA"},
    "NRU" => {"NRU", "NR"},
    "NPL" => {"NEP", "NP"},
    "NLD" => {"NED", "NL"},
    "NCL" => {"NCD", "NC"},
    "NZL" => {"NZL", "NZ"},
    "NIC" => {"NCA", "NI"},
    "NER" => {"NIG", "NE"},
    "NGA" => {"NGR", "NG"},
    "NIU" => {"NIU", "NU"},
    "NFK" => {"NFI", "NF"},
    "MNP" => {"NMA", "MP"},
    "NOR" => {"NOR", "NO"},
    "OMN" => {"OMA", "OM"},
    "PAK" => {"PAK", "PK"},
    "PLW" => {"PLW", "PW"},
    "PAN" => {"PAN", "PA"},
    "PNG" => {"PNG", "PG"},
    "PRY" => {"PAR", "PY"},
    "PER" => {"PER", "PE"},
    "PHL" => {"PHI", "PH"},
    "PCN" => {nil, "PN"},
    "POL" => {"POL", "PL"},
    "PRT" => {"POR", "PT"},
    "PRI" => {"PUR", "PR"},
    "QAT" => {"QAT", "QA"},
    "KOR" => {"KOR", "KR"},
    "MDA" => {"MDA", "MD"},
    "ROU" => {"ROU", "RO"},
    "RUS" => {"RUS", "RU"},
    "RWA" => {"RWA", "RW"},
    "REU" => {"REU", "RE"},
    "BLM" => {nil, "BL"},
    "SHN" => {"HEL", "SH"},
    "KNA" => {"SKN", "KN"},
    "LCA" => {"LCA", "LC"},
    "MAF" => {nil, "MF"},
    "SPM" => {"SPM", "PM"},
    "VCT" => {"VIN", "VC"},
    "WSM" => {"SAM", "WS"},
    "SMR" => {"SMR", "SM"},
    "STP" => {"STP", "ST"},
    "SAU" => {"KSA", "SA"},
    "SEN" => {"SEN", "SN"},
    "SRB" => {"SRB", "RS"},
    "SYC" => {"SEY", "SC"},
    "SLE" => {"SLE", "SL"},
    "SGP" => {"SIN", "SG"},
    "SXM" => {nil, "SX"},
    "SVK" => {"SVK", "SK"},
    "SVN" => {"SLO", "SI"},
    "SLB" => {"SOL", "SB"},
    "SOM" => {"SOM", "SO"},
    "ZAF" => {"RSA", "ZA"},
    "SGS" => {nil, "GS"},
    "SSD" => {nil, "SS"},
    "ESP" => {"ESP", "ES"},
    "LKA" => {"SRI", "LK"},
    "PSE" => {"PLE", "PS"},
    "SDN" => {"SUD", "SD"},
    "SUR" => {"SUR", "SR"},
    "SJM" => {nil, "SJ"},
    "SWZ" => {"SWZ", "SZ"},
    "SWE" => {"SWE", "SE"},
    "CHE" => {"SUI", "CH"},
    "SYR" => {"SYR", "SY"},
    "TJK" => {"TJK", "TJ"},
    "THA" => {"THA", "TH"},
    "MKD" => {"MKD", "MK"},
    "TLS" => {"TLS", "TL"},
    "TGO" => {"TOG", "TG"},
    "TKL" => {nil, "TK"},
    "TON" => {"TGA", "TO"},
    "TTO" => {"TTO", "TT"},
    "TUN" => {"TUN", "TN"},
    "TUR" => {"TUR", "TR"},
    "TKM" => {"TKM", "TM"},
    "TCA" => {"TKS", "TC"},
    "TUV" => {"TUV", "TV"},
    "UGA" => {"UGA", "UG"},
    "UKR" => {"UKR", "UA"},
    "ARE" => {"UAE", "AE"},
    "GBR" => {"GBR", "GB"},
    "TZA" => {"TAN", "TZ"},
    "UMI" => {nil, "UM"},
    "VIR" => {"ISV", "VI"},
    "USA" => {"USA", "US"},
    "URY" => {"URU", "UY"},
    "UZB" => {"UZB", "UZ"},
    "VUT" => {"VAN", "VU"},
    "VEN" => {"VEN", "VE"},
    "VNM" => {"VIE", "VN"},
    "WLF" => {"WAF", "WF"},
    "ESH" => {nil, "EH"},
    "YEM" => {"YEM", "YE"},
    "ZMB" => {"ZAM", "ZM"},
    "ZWE" => {"ZIM", "ZW"},
    "ALA" => {nil, "AX"}
  }

  @ioc %{
    "TPE" => {"TW", "TWN"},
    "AFG" => {"AF", "AFG"},
    "ALB" => {"AL", "ALB"},
    "ALG" => {"DZ", "DZA"},
    "ASA" => {"AS", "ASM"},
    "AND" => {"AD", "AND"},
    "ANG" => {"AO", "AGO"},
    "AIA" => {"AI", "AIA"},
    "ANT" => {"AG", "ATG"},
    "ARG" => {"AR", "ARG"},
    "ARM" => {"AM", "ARM"},
    "ARU" => {"AW", "ABW"},
    "AUS" => {"AU", "AUS"},
    "AUT" => {"AT", "AUT"},
    "AZE" => {"AZ", "AZE"},
    "BAH" => {"BS", "BHS"},
    "BRN" => {"BH", "BHR"},
    "BAN" => {"BD", "BGD"},
    "BAR" => {"BB", "BRB"},
    "BLR" => {"BY", "BLR"},
    "BEL" => {"BE", "BEL"},
    "BIZ" => {"BZ", "BLZ"},
    "BEN" => {"BJ", "BEN"},
    "BER" => {"BM", "BMU"},
    "BHU" => {"BT", "BTN"},
    "BOL" => {"BO", "BOL"},
    "AHO" => {"BQ", "BES"},
    "BIH" => {"BA", "BIH"},
    "BOT" => {"BW", "BWA"},
    "BRA" => {"BR", "BRA"},
    "IVB" => {"VG", "VGB"},
    "BRU" => {"BN", "BRN"},
    "BUL" => {"BG", "BGR"},
    "BUR" => {"BF", "BFA"},
    "BDI" => {"BI", "BDI"},
    "CPV" => {"CV", "CPV"},
    "CAM" => {"KH", "KHM"},
    "CMR" => {"CM", "CMR"},
    "CAN" => {"CA", "CAN"},
    "CAY" => {"KY", "CYM"},
    "CAF" => {"CF", "CAF"},
    "CHA" => {"TD", "TCD"},
    "CHI" => {"CL", "CHL"},
    "CHN" => {"CN", "CHN"},
    "HKG" => {"HK", "HKG"},
    "MAC" => {"MO", "MAC"},
    "COL" => {"CO", "COL"},
    "COM" => {"KM", "COM"},
    "CGO" => {"CG", "COG"},
    "COK" => {"CK", "COK"},
    "CRC" => {"CR", "CRI"},
    "CRO" => {"HR", "HRV"},
    "CUB" => {"CU", "CUB"},
    "CYP" => {"CY", "CYP"},
    "CZE" => {"CZ", "CZE"},
    "CIV" => {"CI", "CIV"},
    "PRK" => {"KP", "PRK"},
    "COD" => {"CD", "COD"},
    "DEN" => {"DK", "DNK"},
    "DJI" => {"DJ", "DJI"},
    "DMA" => {"DM", "DMA"},
    "DOM" => {"DO", "DOM"},
    "ECU" => {"EC", "ECU"},
    "EGY" => {"EG", "EGY"},
    "ESA" => {"SV", "SLV"},
    "GEQ" => {"GQ", "GNQ"},
    "ERI" => {"ER", "ERI"},
    "EST" => {"EE", "EST"},
    "ETH" => {"ET", "ETH"},
    "FLK" => {"FK", "FLK"},
    "FAR" => {"FO", "FRO"},
    "FIJ" => {"FJ", "FJI"},
    "FIN" => {"FI", "FIN"},
    "FRA" => {"FR", "FRA"},
    "FGU" => {"GF", "GUF"},
    "FPO" => {"PF", "PYF"},
    "GAB" => {"GA", "GAB"},
    "GAM" => {"GM", "GMB"},
    "GEO" => {"GE", "GEO"},
    "GER" => {"DE", "DEU"},
    "GHA" => {"GH", "GHA"},
    "GIB" => {"GI", "GIB"},
    "GRE" => {"GR", "GRC"},
    "GRL" => {"GL", "GRL"},
    "GRN" => {"GD", "GRD"},
    "GUD" => {"GP", "GLP"},
    "GUM" => {"GU", "GUM"},
    "GUA" => {"GT", "GTM"},
    "GUI" => {"GN", "GIN"},
    "GBS" => {"GW", "GNB"},
    "GUY" => {"GY", "GUY"},
    "HAI" => {"HT", "HTI"},
    "HON" => {"HN", "HND"},
    "HUN" => {"HU", "HUN"},
    "ISL" => {"IS", "ISL"},
    "IND" => {"IN", "IND"},
    "INA" => {"ID", "IDN"},
    "IRI" => {"IR", "IRN"},
    "IRQ" => {"IQ", "IRQ"},
    "IRL" => {"IE", "IRL"},
    "ISR" => {"IL", "ISR"},
    "ITA" => {"IT", "ITA"},
    "JAM" => {"JM", "JAM"},
    "JPN" => {"JP", "JPN"},
    "JOR" => {"JO", "JOR"},
    "KAZ" => {"KZ", "KAZ"},
    "KEN" => {"KE", "KEN"},
    "KIR" => {"KI", "KIR"},
    "KUW" => {"KW", "KWT"},
    "KGZ" => {"KG", "KGZ"},
    "LAO" => {"LA", "LAO"},
    "LAT" => {"LV", "LVA"},
    "LIB" => {"LB", "LBN"},
    "LES" => {"LS", "LSO"},
    "LBR" => {"LR", "LBR"},
    "LBA" => {"LY", "LBY"},
    "LIE" => {"LI", "LIE"},
    "LTU" => {"LT", "LTU"},
    "LUX" => {"LU", "LUX"},
    "MAD" => {"MG", "MDG"},
    "MAW" => {"MW", "MWI"},
    "MAS" => {"MY", "MYS"},
    "MDV" => {"MV", "MDV"},
    "MLI" => {"ML", "MLI"},
    "MLT" => {"MT", "MLT"},
    "MSH" => {"MH", "MHL"},
    "MRT" => {"MQ", "MTQ"},
    "MTN" => {"MR", "MRT"},
    "MRI" => {"MU", "MUS"},
    "MAY" => {"YT", "MYT"},
    "MEX" => {"MX", "MEX"},
    "FSM" => {"FM", "FSM"},
    "MON" => {"MC", "MCO"},
    "MGL" => {"MN", "MNG"},
    "MGO" => {"ME", "MNE"},
    "MNT" => {"MS", "MSR"},
    "MAR" => {"MA", "MAR"},
    "MOZ" => {"MZ", "MOZ"},
    "MYA" => {"MM", "MMR"},
    "NAM" => {"NA", "NAM"},
    "NRU" => {"NR", "NRU"},
    "NEP" => {"NP", "NPL"},
    "NED" => {"NL", "NLD"},
    "NCD" => {"NC", "NCL"},
    "NZL" => {"NZ", "NZL"},
    "NCA" => {"NI", "NIC"},
    "NIG" => {"NE", "NER"},
    "NGR" => {"NG", "NGA"},
    "NIU" => {"NU", "NIU"},
    "NFI" => {"NF", "NFK"},
    "NMA" => {"MP", "MNP"},
    "NOR" => {"NO", "NOR"},
    "OMA" => {"OM", "OMN"},
    "PAK" => {"PK", "PAK"},
    "PLW" => {"PW", "PLW"},
    "PAN" => {"PA", "PAN"},
    "PNG" => {"PG", "PNG"},
    "PAR" => {"PY", "PRY"},
    "PER" => {"PE", "PER"},
    "PHI" => {"PH", "PHL"},
    "POL" => {"PL", "POL"},
    "POR" => {"PT", "PRT"},
    "PUR" => {"PR", "PRI"},
    "QAT" => {"QA", "QAT"},
    "KOR" => {"KR", "KOR"},
    "MDA" => {"MD", "MDA"},
    "ROU" => {"RO", "ROU"},
    "RUS" => {"RU", "RUS"},
    "RWA" => {"RW", "RWA"},
    "REU" => {"RE", "REU"},
    "HEL" => {"SH", "SHN"},
    "SKN" => {"KN", "KNA"},
    "LCA" => {"LC", "LCA"},
    "SPM" => {"PM", "SPM"},
    "VIN" => {"VC", "VCT"},
    "SAM" => {"WS", "WSM"},
    "SMR" => {"SM", "SMR"},
    "STP" => {"ST", "STP"},
    "KSA" => {"SA", "SAU"},
    "SEN" => {"SN", "SEN"},
    "SRB" => {"RS", "SRB"},
    "SEY" => {"SC", "SYC"},
    "SLE" => {"SL", "SLE"},
    "SIN" => {"SG", "SGP"},
    "SVK" => {"SK", "SVK"},
    "SLO" => {"SI", "SVN"},
    "SOL" => {"SB", "SLB"},
    "SOM" => {"SO", "SOM"},
    "RSA" => {"ZA", "ZAF"},
    "ESP" => {"ES", "ESP"},
    "SRI" => {"LK", "LKA"},
    "PLE" => {"PS", "PSE"},
    "SUD" => {"SD", "SDN"},
    "SUR" => {"SR", "SUR"},
    "SWZ" => {"SZ", "SWZ"},
    "SWE" => {"SE", "SWE"},
    "SUI" => {"CH", "CHE"},
    "SYR" => {"SY", "SYR"},
    "TJK" => {"TJ", "TJK"},
    "THA" => {"TH", "THA"},
    "MKD" => {"MK", "MKD"},
    "TLS" => {"TL", "TLS"},
    "TOG" => {"TG", "TGO"},
    "TGA" => {"TO", "TON"},
    "TTO" => {"TT", "TTO"},
    "TUN" => {"TN", "TUN"},
    "TUR" => {"TR", "TUR"},
    "TKM" => {"TM", "TKM"},
    "TKS" => {"TC", "TCA"},
    "TUV" => {"TV", "TUV"},
    "UGA" => {"UG", "UGA"},
    "UKR" => {"UA", "UKR"},
    "UAE" => {"AE", "ARE"},
    "GBR" => {"GB", "GBR"},
    "TAN" => {"TZ", "TZA"},
    "ISV" => {"VI", "VIR"},
    "USA" => {"US", "USA"},
    "URU" => {"UY", "URY"},
    "UZB" => {"UZ", "UZB"},
    "VAN" => {"VU", "VUT"},
    "VEN" => {"VE", "VEN"},
    "VIE" => {"VN", "VNM"},
    "WAF" => {"WF", "WLF"},
    "YEM" => {"YE", "YEM"},
    "ZAM" => {"ZM", "ZMB"},
    "ZIM" => {"ZW", "ZWE"}
  }

  @iso2_countries Map.keys(@iso2)
  @iso3_countries Map.keys(@iso3)
  @ioc_countries Map.keys(@ioc)

  @type code() :: :iso2 | :iso3 | :ioc
  @type res() :: %{iso2: binary(), iso3: binary(), ioc: binary()}

  @doc """
  Return a country list for a given iso code.

  Returns `{:ok, [binary()]}` or `{:error, binary()}`.

  ## Parameters
    - iso: ISO code, can be one of [:iso2, :iso3, :ioc]

  ## Examples

      iex> {:ok, countries} = CountryCodeConverter.countries(:iso2)
      iex> Enum.member?(countries, "BR")
      true

  """
  @spec countries(code()) :: {:ok, [binary()]} | {:error, binary()}
  def countries(:iso2), do: {:ok, @iso2_countries}
  def countries(:iso3), do: {:ok, @iso3_countries}
  def countries(:ioc), do: {:ok, @ioc_countries}
  def countries(iso), do: {:error, "unknown country iso code type: #{iso}"}

  @doc """
  Converts provided code to all 3 types: iso2, iso3 and ioc.
  Returns `{:ok, %{iso2: binary(), iso3: binary(), ioc: binary()}}` or `{:error, binary()}`.

  ## Parameters
    - iso: ISO code, can be one of [:iso2, :iso3, :ioc]
    - code: code of country in provided ISO, in e.g. ("BRA")

  ## Examples

      iex> CountryCodeConverter.convert(:iso2, "BR")
      {:ok, %{iso2: "BR", iso3: "BRA", ioc: "BRA"}}

  """
  @spec convert(code(), binary()) :: {:ok, res()} | {:error, binary()}
  def convert(:iso2, code), do: do_covert(@iso2, code, [:ioc, :iso3, :iso2])
  def convert(:iso3, code), do: do_covert(@iso3, code, [:ioc, :iso2, :iso3])
  def convert(:ioc, code), do: do_covert(@ioc, code, [:iso2, :iso3, :ioc])
  def convert(iso, _), do: {:error, "unknown country iso code type: #{iso}"}

  defp do_covert(m, code, codes) do
    case Map.get(m, code) do
      nil ->
        {:error, "uknown country code #{code}"}

      {a, b} ->
        res = Map.new(Enum.zip(codes, [a, b, code]))
        {:ok, res}
    end
  end
end