/**
 * Country Code Enum
 *
 * <a href="http://en.wikipedia.org/wiki/ISO_3166-1">ISO 3166-1</a> country code.
 */

export enum CountryCode {
  AD = "AD",
  AE = "AE",
  AF = "AF",
  AG = "AG",
  AI = "AI",
  AL = "AL",
  AM = "AM",
  AO = "AO",
  AQ = "AQ",
  AR = "AR",
  AS = "AS",
  AT = "AT",
  AU = "AU",
  AW = "AW",
  AX = "AX",
  AZ = "AZ",
  BA = "BA",
  BB = "BB",
  BD = "BD",
  BE = "BE",
  BF = "BF",
  BG = "BG",
  BH = "BH",
  BI = "BI",
  BJ = "BJ",
  BL = "BL",
  BM = "BM",
  BN = "BN",
  BO = "BO",
  BQ = "BQ",
  BR = "BR",
  BS = "BS",
  BT = "BT",
  BV = "BV",
  BW = "BW",
  BY = "BY",
  BZ = "BZ",
  CA = "CA",
  CC = "CC",
  CD = "CD",
  CF = "CF",
  CG = "CG",
  CH = "CH",
  CI = "CI",
  CK = "CK",
  CL = "CL",
  CM = "CM",
  CN = "CN",
  CO = "CO",
  CR = "CR",
  CU = "CU",
  CV = "CV",
  CW = "CW",
  CX = "CX",
  CY = "CY",
  CZ = "CZ",
  DE = "DE",
  DJ = "DJ",
  DK = "DK",
  DM = "DM",
  DO = "DO",
  DZ = "DZ",
  EC = "EC",
  EE = "EE",
  EG = "EG",
  EH = "EH",
  ER = "ER",
  ES = "ES",
  ET = "ET",
  FI = "FI",
  FJ = "FJ",
  FK = "FK",
  FM = "FM",
  FO = "FO",
  FR = "FR",
  GA = "GA",
  GB = "GB",
  GD = "GD",
  GE = "GE",
  GF = "GF",
  GG = "GG",
  GH = "GH",
  GI = "GI",
  GL = "GL",
  GM = "GM",
  GN = "GN",
  GP = "GP",
  GQ = "GQ",
  GR = "GR",
  GS = "GS",
  GT = "GT",
  GU = "GU",
  GW = "GW",
  GY = "GY",
  HK = "HK",
  HM = "HM",
  HN = "HN",
  HR = "HR",
  HT = "HT",
  HU = "HU",
  ID = "ID",
  IE = "IE",
  IL = "IL",
  IM = "IM",
  IN = "IN",
  IO = "IO",
  IQ = "IQ",
  IR = "IR",
  IS = "IS",
  IT = "IT",
  JE = "JE",
  JM = "JM",
  JO = "JO",
  JP = "JP",
  KE = "KE",
  KG = "KG",
  KH = "KH",
  KI = "KI",
  KM = "KM",
  KN = "KN",
  KP = "KP",
  KR = "KR",
  KW = "KW",
  KY = "KY",
  KZ = "KZ",
  LA = "LA",
  LB = "LB",
  LC = "LC",
  LI = "LI",
  LK = "LK",
  LR = "LR",
  LS = "LS",
  LT = "LT",
  LU = "LU",
  LV = "LV",
  LY = "LY",
  MA = "MA",
  MC = "MC",
  MD = "MD",
  ME = "ME",
  MF = "MF",
  MG = "MG",
  MH = "MH",
  MK = "MK",
  ML = "ML",
  MM = "MM",
  MN = "MN",
  MO = "MO",
  MP = "MP",
  MQ = "MQ",
  MR = "MR",
  MS = "MS",
  MT = "MT",
  MU = "MU",
  MV = "MV",
  MW = "MW",
  MX = "MX",
  MY = "MY",
  MZ = "MZ",
  NA = "NA",
  NC = "NC",
  NE = "NE",
  NF = "NF",
  NG = "NG",
  NI = "NI",
  NL = "NL",
  NO = "NO",
  NP = "NP",
  NR = "NR",
  NU = "NU",
  NZ = "NZ",
  OM = "OM",
  PA = "PA",
  PE = "PE",
  PF = "PF",
  PG = "PG",
  PH = "PH",
  PK = "PK",
  PL = "PL",
  PM = "PM",
  PN = "PN",
  PR = "PR",
  PS = "PS",
  PT = "PT",
  PW = "PW",
  PY = "PY",
  QA = "QA",
  RE = "RE",
  RO = "RO",
  RS = "RS",
  RU = "RU",
  RW = "RW",
  SA = "SA",
  SB = "SB",
  SC = "SC",
  SD = "SD",
  SE = "SE",
  SG = "SG",
  SH = "SH",
  SI = "SI",
  SJ = "SJ",
  SK = "SK",
  SL = "SL",
  SM = "SM",
  SN = "SN",
  SO = "SO",
  SR = "SR",
  SS = "SS",
  ST = "ST",
  SV = "SV",
  SX = "SX",
  SY = "SY",
  SZ = "SZ",
  TC = "TC",
  TD = "TD",
  TF = "TF",
  TG = "TG",
  TH = "TH",
  TJ = "TJ",
  TK = "TK",
  TL = "TL",
  TM = "TM",
  TN = "TN",
  TO = "TO",
  TR = "TR",
  TT = "TT",
  TV = "TV",
  TW = "TW",
  TZ = "TZ",
  UA = "UA",
  UG = "UG",
  UM = "UM",
  US = "US",
  UY = "UY",
  UZ = "UZ",
  VA = "VA",
  VC = "VC",
  VE = "VE",
  VG = "VG",
  VI = "VI",
  VN = "VN",
  VU = "VU",
  WF = "WF",
  WS = "WS",
  XK = "XK",
  YE = "YE",
  YT = "YT",
  ZA = "ZA",
  ZM = "ZM",
  ZW = "ZW",
}

const countryData: Record<CountryCode, [string, string]> = {
  [CountryCode.AD]: ["Andorra", "AND"],
  [CountryCode.AE]: ["United Arab Emirates", "ARE"],
  [CountryCode.AF]: ["Afghanistan", "AFG"],
  [CountryCode.AG]: ["Antigua and Barbuda", "ATG"],
  [CountryCode.AI]: ["Anguilla", "AIA"],
  [CountryCode.AL]: ["Albania", "ALB"],
  [CountryCode.AM]: ["Armenia", "ARM"],
  [CountryCode.AO]: ["Angola", "AGO"],
  [CountryCode.AQ]: ["Antarctica", "ATA"],
  [CountryCode.AR]: ["Argentina", "ARG"],
  [CountryCode.AS]: ["American Samoa", "ASM"],
  [CountryCode.AT]: ["Austria", "AUT"],
  [CountryCode.AU]: ["Australia", "AUS"],
  [CountryCode.AW]: ["Aruba", "ABW"],
  [CountryCode.AX]: ["\u212Bland Islands", "ALA"],
  [CountryCode.AZ]: ["Azerbaijan", "AZE"],
  [CountryCode.BA]: ["Bosnia and Herzegovina", "BIH"],
  [CountryCode.BB]: ["Barbados", "BRB"],
  [CountryCode.BD]: ["Bangladesh", "BGD"],
  [CountryCode.BE]: ["Belgium", "BEL"],
  [CountryCode.BF]: ["Burkina Faso", "BFA"],
  [CountryCode.BG]: ["Bulgaria", "BGR"],
  [CountryCode.BH]: ["Bahrain", "BHR"],
  [CountryCode.BI]: ["Burundi", "BDI"],
  [CountryCode.BJ]: ["Benin", "BEN"],
  [CountryCode.BL]: ["Saint Barth\u00E9lemy", "BLM"],
  [CountryCode.BM]: ["Bermuda", "BMU"],
  [CountryCode.BN]: ["Brunei Darussalam", "BRN"],
  [CountryCode.BO]: ["Plurinational State of Bolivia", "BOL"],
  [CountryCode.BQ]: ["Bonaire, Sint Eustatius and Saba", "BES"],
  [CountryCode.BR]: ["Brazil", "BRA"],
  [CountryCode.BS]: ["Bahamas", "BHS"],
  [CountryCode.BT]: ["Bhutan", "BTN"],
  [CountryCode.BV]: ["Bouvet Island", "BVT"],
  [CountryCode.BW]: ["Botswana", "BWA"],
  [CountryCode.BY]: ["Belarus", "BLR"],
  [CountryCode.BZ]: ["Belize", "BLZ"],
  [CountryCode.CA]: ["Canada", "CAN"],
  [CountryCode.CC]: ["Cocos Islands", "CCK"],
  [CountryCode.CD]: ["The Democratic Republic of the Congo", "COD"],
  [CountryCode.CF]: ["Central African Republic", "CAF"],
  [CountryCode.CG]: ["Congo", "COG"],
  [CountryCode.CH]: ["Switzerland", "CHE"],
  [CountryCode.CI]: ["C\u00F4te d'Ivoire", "CIV"],
  [CountryCode.CK]: ["Cook Islands", "COK"],
  [CountryCode.CL]: ["Chile", "CHL"],
  [CountryCode.CM]: ["Cameroon", "CMR"],
  [CountryCode.CN]: ["China", "CHN"],
  [CountryCode.CO]: ["Colombia", "COL"],
  [CountryCode.CR]: ["Costa Rica", "CRI"],
  [CountryCode.CU]: ["Cuba", "CUB"],
  [CountryCode.CV]: ["Cape Verde", "CPV"],
  [CountryCode.CW]: ["Cura\u00E7ao", "CUW"],
  [CountryCode.CX]: ["Christmas Island", "CXR"],
  [CountryCode.CY]: ["Cyprus", "CYP"],
  [CountryCode.CZ]: ["Czech Republic", "CZE"],
  [CountryCode.DE]: ["Germany", "DEU"],
  [CountryCode.DJ]: ["Djibouti", "DJI"],
  [CountryCode.DK]: ["Denmark", "DNK"],
  [CountryCode.DM]: ["Dominica", "DMA"],
  [CountryCode.DO]: ["Dominican Republic", "DOM"],
  [CountryCode.DZ]: ["Algeria", "DZA"],
  [CountryCode.EC]: ["Ecuador", "ECU"],
  [CountryCode.EE]: ["Estonia", "EST"],
  [CountryCode.EG]: ["Egypt", "EGY"],
  [CountryCode.EH]: ["Western Sahara", "ESH"],
  [CountryCode.ER]: ["Eritrea", "ERI"],
  [CountryCode.ES]: ["Spain", "ESP"],
  [CountryCode.ET]: ["Ethiopia", "ETH"],
  [CountryCode.FI]: ["Finland", "FIN"],
  [CountryCode.FJ]: ["Fiji", "FJI"],
  [CountryCode.FK]: ["Falkland Islands", "FLK"],
  [CountryCode.FM]: ["Federated States of Micronesia", "FSM"],
  [CountryCode.FO]: ["Faroe Islands", "FRO"],
  [CountryCode.FR]: ["France", "FRA"],
  [CountryCode.GA]: ["Gabon", "GAB"],
  [CountryCode.GB]: ["United Kingdom", "GBR"],
  [CountryCode.GD]: ["Grenada", "GRD"],
  [CountryCode.GE]: ["Georgia", "GEO"],
  [CountryCode.GF]: ["French Guiana", "GUF"],
  [CountryCode.GG]: ["Guemsey", "GGY"],
  [CountryCode.GH]: ["Ghana", "GHA"],
  [CountryCode.GI]: ["Gibraltar", "GIB"],
  [CountryCode.GL]: ["Greenland", "GRL"],
  [CountryCode.GM]: ["Gambia", "GMB"],
  [CountryCode.GN]: ["Guinea", "GIN"],
  [CountryCode.GP]: ["Guadeloupe", "GLP"],
  [CountryCode.GQ]: ["Equatorial Guinea", "GNQ"],
  [CountryCode.GR]: ["Greece", "GRC"],
  [CountryCode.GS]: ["South Georgia and the South Sandwich Islands", "SGS"],
  [CountryCode.GT]: ["Guatemala", "GTM"],
  [CountryCode.GU]: ["Guam", "GUM"],
  [CountryCode.GW]: ["Guinea-Bissau", "GNB"],
  [CountryCode.GY]: ["Guyana", "GUY"],
  [CountryCode.HK]: ["Hong Kong", "HKG"],
  [CountryCode.HM]: ["Heard Island and McDonald Islands", "HMD"],
  [CountryCode.HN]: ["Honduras", "HND"],
  [CountryCode.HR]: ["Croatia", "HRV"],
  [CountryCode.HT]: ["Haiti", "HTI"],
  [CountryCode.HU]: ["Hungary", "HUN"],
  [CountryCode.ID]: ["Indonesia", "IDN"],
  [CountryCode.IE]: ["Ireland", "IRL"],
  [CountryCode.IL]: ["Israel", "ISR"],
  [CountryCode.IM]: ["Isle of Man", "IMN"],
  [CountryCode.IN]: ["India", "IND"],
  [CountryCode.IO]: ["British Indian Ocean Territory", "IOT"],
  [CountryCode.IQ]: ["Iraq", "IRQ"],
  [CountryCode.IR]: ["Islamic Republic of Iran", "IRN"],
  [CountryCode.IS]: ["Iceland", "ISL"],
  [CountryCode.IT]: ["Italy", "ITA"],
  [CountryCode.JE]: ["Jersey", "JEY"],
  [CountryCode.JM]: ["Jamaica", "JAM"],
  [CountryCode.JO]: ["Jordan", "JOR"],
  [CountryCode.JP]: ["Japan", "JPN"],
  [CountryCode.KE]: ["Kenya", "KEN"],
  [CountryCode.KG]: ["Kyrgyzstan", "KGZ"],
  [CountryCode.KH]: ["Cambodia", "KHM"],
  [CountryCode.KI]: ["Kiribati", "KIR"],
  [CountryCode.KM]: ["Comoros", "COM"],
  [CountryCode.KN]: ["Saint Kitts and Nevis", "KNA"],
  [CountryCode.KP]: ["Democratic People's Republic of Korea", "PRK"],
  [CountryCode.KR]: ["Republic of Korea", "KOR"],
  [CountryCode.KW]: ["Kuwait", "KWT"],
  [CountryCode.KY]: ["Cayman Islands", "CYM"],
  [CountryCode.KZ]: ["Kazakhstan", "KAZ"],
  [CountryCode.LA]: ["Lao People's Democratic Republic", "LAO"],
  [CountryCode.LB]: ["Lebanon", "LBN"],
  [CountryCode.LC]: ["Saint Lucia", "LCA"],
  [CountryCode.LI]: ["Liechtenstein", "LIE"],
  [CountryCode.LK]: ["Sri Lanka", "LKA"],
  [CountryCode.LR]: ["Liberia", "LBR"],
  [CountryCode.LS]: ["Lesotho", "LSO"],
  [CountryCode.LT]: ["Lithuania", "LTU"],
  [CountryCode.LU]: ["Luxembourg", "LUX"],
  [CountryCode.LV]: ["Latvia", "LVA"],
  [CountryCode.LY]: ["Libya", "LBY"],
  [CountryCode.MA]: ["Morocco", "MAR"],
  [CountryCode.MC]: ["Monaco", "MCO"],
  [CountryCode.MD]: ["Republic of Moldova", "MDA"],
  [CountryCode.ME]: ["Montenegro", "MNE"],
  [CountryCode.MF]: ["Saint Martin", "MAF"],
  [CountryCode.MG]: ["Madagascar", "MDG"],
  [CountryCode.MH]: ["Marshall Islands", "MHL"],
  [CountryCode.MK]: ["The former Yugoslav Republic of Macedonia", "MKD"],
  [CountryCode.ML]: ["Mali", "MLI"],
  [CountryCode.MM]: ["Myanmar", "MMR"],
  [CountryCode.MN]: ["Mongolia", "MNG"],
  [CountryCode.MO]: ["Macao", "MAC"],
  [CountryCode.MP]: ["Northern Mariana Islands", "MNP"],
  [CountryCode.MQ]: ["Martinique", "MTQ"],
  [CountryCode.MR]: ["Mauritania", "MRT"],
  [CountryCode.MS]: ["Montserrat", "MSR"],
  [CountryCode.MT]: ["Malta", "MLT"],
  [CountryCode.MU]: ["Mauritius", "MUS"],
  [CountryCode.MV]: ["Maldives", "MDV"],
  [CountryCode.MW]: ["Malawi", "MWI"],
  [CountryCode.MX]: ["Mexico", "MEX"],
  [CountryCode.MY]: ["Malaysia", "MYS"],
  [CountryCode.MZ]: ["Mozambique", "MOZ"],
  [CountryCode.NA]: ["Namibia", "NAM"],
  [CountryCode.NC]: ["New Caledonia", "NCL"],
  [CountryCode.NE]: ["Niger", "NER"],
  [CountryCode.NF]: ["Norfolk Island", "NFK"],
  [CountryCode.NG]: ["Nigeria", "NGA"],
  [CountryCode.NI]: ["Nicaragua", "NIC"],
  [CountryCode.NL]: ["Netherlands", "NLD"],
  [CountryCode.NO]: ["Norway", "NOR"],
  [CountryCode.NP]: ["Nepal", "NPL"],
  [CountryCode.NR]: ["Nauru", "NRU"],
  [CountryCode.NU]: ["Niue", "NIU"],
  [CountryCode.NZ]: ["New Zealand", "NZL"],
  [CountryCode.OM]: ["Oman", "OMN"],
  [CountryCode.PA]: ["Panama", "PAN"],
  [CountryCode.PE]: ["Peru", "PER"],
  [CountryCode.PF]: ["French Polynesia", "PYF"],
  [CountryCode.PG]: ["Papua New Guinea", "PNG"],
  [CountryCode.PH]: ["Philippines", "PHL"],
  [CountryCode.PK]: ["Pakistan", "PAK"],
  [CountryCode.PL]: ["Poland", "POL"],
  [CountryCode.PM]: ["Saint Pierre and Miquelon", "SPM"],
  [CountryCode.PN]: ["Pitcairn", "PCN"],
  [CountryCode.PR]: ["Puerto Rico", "PRI"],
  [CountryCode.PS]: ["Occupied Palestinian Territory", "PSE"],
  [CountryCode.PT]: ["Portugal", "PRT"],
  [CountryCode.PW]: ["Palau", "PLW"],
  [CountryCode.PY]: ["Paraguay", "PRY"],
  [CountryCode.QA]: ["Qatar", "QAT"],
  [CountryCode.RE]: ["R\u00E9union", "REU"],
  [CountryCode.RO]: ["Romania", "ROU"],
  [CountryCode.RS]: ["Serbia", "SRB"],
  [CountryCode.RU]: ["Russian Federation", "RUS"],
  [CountryCode.RW]: ["Rwanda", "RWA"],
  [CountryCode.SA]: ["Saudi Arabia", "SAU"],
  [CountryCode.SB]: ["Solomon Islands", "SLB"],
  [CountryCode.SC]: ["Seychelles", "SYC"],
  [CountryCode.SD]: ["Sudan", "SDN"],
  [CountryCode.SE]: ["Sweden", "SWE"],
  [CountryCode.SG]: ["Singapore", "SGP"],
  [CountryCode.SH]: ["Saint Helena, Ascension and Tristan da Cunha", "SHN"],
  [CountryCode.SI]: ["Slovenia", "SVN"],
  [CountryCode.SJ]: ["Svalbard and Jan Mayen", "SJM"],
  [CountryCode.SK]: ["Slovakia", "SVK"],
  [CountryCode.SL]: ["Sierra Leone", "SLE"],
  [CountryCode.SM]: ["San Marino", "SMR"],
  [CountryCode.SN]: ["Senegal", "SEN"],
  [CountryCode.SO]: ["Somalia", "SOM"],
  [CountryCode.SR]: ["Suriname", "SUR"],
  [CountryCode.SS]: ["South Sudan", "SSD"],
  [CountryCode.ST]: ["Sao Tome and Principe", "STP"],
  [CountryCode.SV]: ["El Salvador", "SLV"],
  [CountryCode.SX]: ["Sint Maarten", "SXM"],
  [CountryCode.SY]: ["Syrian Arab Republic", "SYR"],
  [CountryCode.SZ]: ["Swaziland", "SWZ"],
  [CountryCode.TC]: ["Turks and Caicos Islands", "TCA"],
  [CountryCode.TD]: ["Chad", "TCD"],
  [CountryCode.TF]: ["French Southern Territories", "ATF"],
  [CountryCode.TG]: ["Togo", "TGO"],
  [CountryCode.TH]: ["Thailand", "THA"],
  [CountryCode.TJ]: ["Tajikistan", "TJK"],
  [CountryCode.TK]: ["Tokelau", "TKL"],
  [CountryCode.TL]: ["Timor-Leste", "TLS"],
  [CountryCode.TM]: ["Turkmenistan", "TKM"],
  [CountryCode.TN]: ["Tunisia", "TUN"],
  [CountryCode.TO]: ["Tonga", "TON"],
  [CountryCode.TR]: ["Turkey", "TUR"],
  [CountryCode.TT]: ["Trinidad and Tobago", "TTO"],
  [CountryCode.TV]: ["Tuvalu", "TUV"],
  [CountryCode.TW]: ["Taiwan, Province of China", "TWN"],
  [CountryCode.TZ]: ["United Republic of Tanzania", "TZA"],
  [CountryCode.UA]: ["Ukraine", "UKR"],
  [CountryCode.UG]: ["Uganda", "UGA"],
  [CountryCode.UM]: ["United States Minor Outlying Islands", "UMI"],
  [CountryCode.US]: ["United States", "USA"],
  [CountryCode.UY]: ["Uruguay", "URY"],
  [CountryCode.UZ]: ["Uzbekistan", "UZB"],
  [CountryCode.VA]: ["Holy See", "VAT"],
  [CountryCode.VC]: ["Saint Vincent and the Grenadines", "VCT"],
  [CountryCode.VE]: ["Bolivarian Republic of Venezuela", "VEN"],
  [CountryCode.VG]: ["British Virgin Islands", "VGB"],
  [CountryCode.VI]: ["Virgin Islands, U.S.", "VIR"],
  [CountryCode.VN]: ["Viet Nam", "VNM"],
  [CountryCode.VU]: ["Vanuatu", "VUT"],
  [CountryCode.WF]: ["Wallis and Futuna", "WLF"],
  [CountryCode.WS]: ["Samoa", "WSM"],
  [CountryCode.XK]: ["Kosovo", "UNK"],
  [CountryCode.YE]: ["Yemen", "YEM"],
  [CountryCode.YT]: ["Mayotte", "MYT"],
  [CountryCode.ZA]: ["South Africa", "ZAF"],
  [CountryCode.ZM]: ["Zambia", "ZMB"],
  [CountryCode.ZW]: ["Zimbabwe", "ZWE"],
};

const by2code = Object.entries(countryData).reduce(
  (acc, [k, v]) => {
    acc[k] = [k as CountryCode, v];
    return acc;
  },
  {} as Record<string, [CountryCode, [string, string]]>,
);

const by3code = Object.entries(countryData).reduce(
  (acc, [k, v]) => {
    acc[v[1]] = [k as CountryCode, v];
    return acc;
  },
  {} as Record<string, [CountryCode, [string, string]]>,
);

export function countryByCode(code: string): CountryCode | null {
  if (code === null) {
    return null;
  }

  let info;
  if (code.length === 3) {
    info = by3code[code];
  } else if (code.length === 2) {
    info = by2code[code];
  }
  if (info) {
    return info[0];
  }

  return null;
}
