//
//  locale.cpp
//
//  Created by Stuart Eichert on 3/24/2016
//  Copyright (c) 2016 Anki, Inc. All rights reserved.
//

#include "locale.h"
#include "util/string/stringUtils.h"
#include "util/helpers/ankiDefines.h"
#if defined(ANKI_PLATFORM_IOS) || defined(ANKI_PLATFORM_OSX)
#include "util/environment/locale_iososx.h"
#elif defined(ANKI_PLATFORM_ANDROID)
#include "util/environment/locale_android.h"
#else
#include "util/environment/locale.h"
#endif

#include <map>

namespace Anki {
namespace Util {

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

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

static std::map<Locale::Language, const char* const> sLanguageToString =
  {
    {Locale::Language::aa, "aa"},
    {Locale::Language::ab, "ab"},
    {Locale::Language::ae, "ae"},
    {Locale::Language::af, "af"},
    {Locale::Language::ak, "ak"},
    {Locale::Language::am, "am"},
    {Locale::Language::an, "an"},
    {Locale::Language::ar, "ar"},
    {Locale::Language::as, "as"},
    {Locale::Language::av, "av"},
    {Locale::Language::ay, "ay"},
    {Locale::Language::az, "az"},
    {Locale::Language::ba, "ba"},
    {Locale::Language::be, "be"},
    {Locale::Language::bg, "bg"},
    {Locale::Language::bh, "bh"},
    {Locale::Language::bi, "bi"},
    {Locale::Language::bm, "bm"},
    {Locale::Language::bn, "bn"},
    {Locale::Language::bo, "bo"},
    {Locale::Language::br, "br"},
    {Locale::Language::bs, "bs"},
    {Locale::Language::ca, "ca"},
    {Locale::Language::ce, "ce"},
    {Locale::Language::ch, "ch"},
    {Locale::Language::co, "co"},
    {Locale::Language::cr, "cr"},
    {Locale::Language::cs, "cs"},
    {Locale::Language::cu, "cu"},
    {Locale::Language::cv, "cv"},
    {Locale::Language::cy, "cy"},
    {Locale::Language::da, "da"},
    {Locale::Language::de, "de"},
    {Locale::Language::dv, "dv"},
    {Locale::Language::dz, "dz"},
    {Locale::Language::ee, "ee"},
    {Locale::Language::el, "el"},
    {Locale::Language::en, "en"},
    {Locale::Language::eo, "eo"},
    {Locale::Language::es, "es"},
    {Locale::Language::et, "et"},
    {Locale::Language::eu, "eu"},
    {Locale::Language::fa, "fa"},
    {Locale::Language::ff, "ff"},
    {Locale::Language::fi, "fi"},
    {Locale::Language::fj, "fj"},
    {Locale::Language::fo, "fo"},
    {Locale::Language::fr, "fr"},
    {Locale::Language::fy, "fy"},
    {Locale::Language::ga, "ga"},
    {Locale::Language::gd, "gd"},
    {Locale::Language::gl, "gl"},
    {Locale::Language::gn, "gn"},
    {Locale::Language::gu, "gu"},
    {Locale::Language::gv, "gv"},
    {Locale::Language::ha, "ha"},
    {Locale::Language::he, "he"},
    {Locale::Language::hi, "hi"},
    {Locale::Language::ho, "ho"},
    {Locale::Language::hr, "hr"},
    {Locale::Language::ht, "ht"},
    {Locale::Language::hu, "hu"},
    {Locale::Language::hy, "hy"},
    {Locale::Language::hz, "hz"},
    {Locale::Language::ia, "ia"},
    {Locale::Language::id, "id"},
    {Locale::Language::ie, "ie"},
    {Locale::Language::ig, "ig"},
    {Locale::Language::ii, "ii"},
    {Locale::Language::ik, "ik"},
    {Locale::Language::io, "io"},
    {Locale::Language::is, "is"},
    {Locale::Language::it, "it"},
    {Locale::Language::iu, "iu"},
    {Locale::Language::ja, "ja"},
    {Locale::Language::jv, "jv"},
    {Locale::Language::ka, "ka"},
    {Locale::Language::kg, "kg"},
    {Locale::Language::ki, "ki"},
    {Locale::Language::kj, "kj"},
    {Locale::Language::kk, "kk"},
    {Locale::Language::kl, "kl"},
    {Locale::Language::km, "km"},
    {Locale::Language::kn, "kn"},
    {Locale::Language::ko, "ko"},
    {Locale::Language::kr, "kr"},
    {Locale::Language::ks, "ks"},
    {Locale::Language::ku, "ku"},
    {Locale::Language::kv, "kv"},
    {Locale::Language::kw, "kw"},
    {Locale::Language::ky, "ky"},
    {Locale::Language::la, "la"},
    {Locale::Language::lb, "lb"},
    {Locale::Language::lg, "lg"},
    {Locale::Language::li, "li"},
    {Locale::Language::ln, "ln"},
    {Locale::Language::lo, "lo"},
    {Locale::Language::lt, "lt"},
    {Locale::Language::lu, "lu"},
    {Locale::Language::lv, "lv"},
    {Locale::Language::mg, "mg"},
    {Locale::Language::mh, "mh"},
    {Locale::Language::mi, "mi"},
    {Locale::Language::mk, "mk"},
    {Locale::Language::ml, "ml"},
    {Locale::Language::mn, "mn"},
    {Locale::Language::mr, "mr"},
    {Locale::Language::ms, "ms"},
    {Locale::Language::mt, "mt"},
    {Locale::Language::my, "my"},
    {Locale::Language::na, "na"},
    {Locale::Language::nb, "nb"},
    {Locale::Language::nd, "nd"},
    {Locale::Language::ne, "ne"},
    {Locale::Language::ng, "ng"},
    {Locale::Language::nl, "nl"},
    {Locale::Language::nn, "nn"},
    {Locale::Language::no, "no"},
    {Locale::Language::nr, "nr"},
    {Locale::Language::nv, "nv"},
    {Locale::Language::ny, "ny"},
    {Locale::Language::oc, "oc"},
    {Locale::Language::oj, "oj"},
    {Locale::Language::om, "om"},
    {Locale::Language::oriya, "or"},
    {Locale::Language::os, "os"},
    {Locale::Language::pa, "pa"},
    {Locale::Language::pi, "pi"},
    {Locale::Language::pl, "pl"},
    {Locale::Language::ps, "ps"},
    {Locale::Language::pt, "pt"},
    {Locale::Language::qu, "qu"},
    {Locale::Language::rm, "rm"},
    {Locale::Language::rn, "rn"},
    {Locale::Language::ro, "ro"},
    {Locale::Language::ru, "ru"},
    {Locale::Language::rw, "rw"},
    {Locale::Language::sa, "sa"},
    {Locale::Language::sc, "sc"},
    {Locale::Language::sd, "sd"},
    {Locale::Language::se, "se"},
    {Locale::Language::sg, "sg"},
    {Locale::Language::si, "si"},
    {Locale::Language::sk, "sk"},
    {Locale::Language::sl, "sl"},
    {Locale::Language::sm, "sm"},
    {Locale::Language::sn, "sn"},
    {Locale::Language::so, "so"},
    {Locale::Language::sq, "sq"},
    {Locale::Language::sr, "sr"},
    {Locale::Language::ss, "ss"},
    {Locale::Language::st, "st"},
    {Locale::Language::su, "su"},
    {Locale::Language::sv, "sv"},
    {Locale::Language::sw, "sw"},
    {Locale::Language::ta, "ta"},
    {Locale::Language::te, "te"},
    {Locale::Language::tg, "tg"},
    {Locale::Language::th, "th"},
    {Locale::Language::ti, "ti"},
    {Locale::Language::tk, "tk"},
    {Locale::Language::tl, "tl"},
    {Locale::Language::tn, "tn"},
    {Locale::Language::to, "to"},
    {Locale::Language::tr, "tr"},
    {Locale::Language::ts, "ts"},
    {Locale::Language::tt, "tt"},
    {Locale::Language::tw, "tw"},
    {Locale::Language::ty, "ty"},
    {Locale::Language::ug, "ug"},
    {Locale::Language::uk, "uk"},
    {Locale::Language::ur, "ur"},
    {Locale::Language::uz, "uz"},
    {Locale::Language::ve, "ve"},
    {Locale::Language::vi, "vi"},
    {Locale::Language::vo, "vo"},
    {Locale::Language::wa, "wa"},
    {Locale::Language::wo, "wo"},
    {Locale::Language::xh, "xh"},
    {Locale::Language::yi, "yi"},
    {Locale::Language::yo, "yo"},
    {Locale::Language::za, "za"},
    {Locale::Language::zh, "zh"},
    {Locale::Language::zu, "zu"}
  };

static std::map<const std::string, const Locale::Language> sStringToLanguage =
  {
    {"aa", Locale::Language::aa},
    {"ab", Locale::Language::ab},
    {"ae", Locale::Language::ae},
    {"af", Locale::Language::af},
    {"ak", Locale::Language::ak},
    {"am", Locale::Language::am},
    {"an", Locale::Language::an},
    {"ar", Locale::Language::ar},
    {"as", Locale::Language::as},
    {"av", Locale::Language::av},
    {"ay", Locale::Language::ay},
    {"az", Locale::Language::az},
    {"ba", Locale::Language::ba},
    {"be", Locale::Language::be},
    {"bg", Locale::Language::bg},
    {"bh", Locale::Language::bh},
    {"bi", Locale::Language::bi},
    {"bm", Locale::Language::bm},
    {"bn", Locale::Language::bn},
    {"bo", Locale::Language::bo},
    {"br", Locale::Language::br},
    {"bs", Locale::Language::bs},
    {"ca", Locale::Language::ca},
    {"ce", Locale::Language::ce},
    {"ch", Locale::Language::ch},
    {"co", Locale::Language::co},
    {"cr", Locale::Language::cr},
    {"cs", Locale::Language::cs},
    {"cu", Locale::Language::cu},
    {"cv", Locale::Language::cv},
    {"cy", Locale::Language::cy},
    {"da", Locale::Language::da},
    {"de", Locale::Language::de},
    {"dv", Locale::Language::dv},
    {"dz", Locale::Language::dz},
    {"ee", Locale::Language::ee},
    {"el", Locale::Language::el},
    {"en", Locale::Language::en},
    {"eo", Locale::Language::eo},
    {"es", Locale::Language::es},
    {"et", Locale::Language::et},
    {"eu", Locale::Language::eu},
    {"fa", Locale::Language::fa},
    {"ff", Locale::Language::ff},
    {"fi", Locale::Language::fi},
    {"fj", Locale::Language::fj},
    {"fo", Locale::Language::fo},
    {"fr", Locale::Language::fr},
    {"fy", Locale::Language::fy},
    {"ga", Locale::Language::ga},
    {"gd", Locale::Language::gd},
    {"gl", Locale::Language::gl},
    {"gn", Locale::Language::gn},
    {"gu", Locale::Language::gu},
    {"gv", Locale::Language::gv},
    {"ha", Locale::Language::ha},
    {"he", Locale::Language::he},
    {"hi", Locale::Language::hi},
    {"ho", Locale::Language::ho},
    {"hr", Locale::Language::hr},
    {"ht", Locale::Language::ht},
    {"hu", Locale::Language::hu},
    {"hy", Locale::Language::hy},
    {"hz", Locale::Language::hz},
    {"ia", Locale::Language::ia},
    {"id", Locale::Language::id},
    {"ie", Locale::Language::ie},
    {"ig", Locale::Language::ig},
    {"ii", Locale::Language::ii},
    {"ik", Locale::Language::ik},
    {"io", Locale::Language::io},
    {"is", Locale::Language::is},
    {"it", Locale::Language::it},
    {"iu", Locale::Language::iu},
    {"ja", Locale::Language::ja},
    {"jv", Locale::Language::jv},
    {"ka", Locale::Language::ka},
    {"kg", Locale::Language::kg},
    {"ki", Locale::Language::ki},
    {"kj", Locale::Language::kj},
    {"kk", Locale::Language::kk},
    {"kl", Locale::Language::kl},
    {"km", Locale::Language::km},
    {"kn", Locale::Language::kn},
    {"ko", Locale::Language::ko},
    {"kr", Locale::Language::kr},
    {"ks", Locale::Language::ks},
    {"ku", Locale::Language::ku},
    {"kv", Locale::Language::kv},
    {"kw", Locale::Language::kw},
    {"ky", Locale::Language::ky},
    {"la", Locale::Language::la},
    {"lb", Locale::Language::lb},
    {"lg", Locale::Language::lg},
    {"li", Locale::Language::li},
    {"ln", Locale::Language::ln},
    {"lo", Locale::Language::lo},
    {"lt", Locale::Language::lt},
    {"lu", Locale::Language::lu},
    {"lv", Locale::Language::lv},
    {"mg", Locale::Language::mg},
    {"mh", Locale::Language::mh},
    {"mi", Locale::Language::mi},
    {"mk", Locale::Language::mk},
    {"ml", Locale::Language::ml},
    {"mn", Locale::Language::mn},
    {"mr", Locale::Language::mr},
    {"ms", Locale::Language::ms},
    {"mt", Locale::Language::mt},
    {"my", Locale::Language::my},
    {"na", Locale::Language::na},
    {"nb", Locale::Language::nb},
    {"nd", Locale::Language::nd},
    {"ne", Locale::Language::ne},
    {"ng", Locale::Language::ng},
    {"nl", Locale::Language::nl},
    {"nn", Locale::Language::nn},
    {"no", Locale::Language::no},
    {"nr", Locale::Language::nr},
    {"nv", Locale::Language::nv},
    {"ny", Locale::Language::ny},
    {"oc", Locale::Language::oc},
    {"oj", Locale::Language::oj},
    {"om", Locale::Language::om},
    {"or", Locale::Language::oriya},
    {"os", Locale::Language::os},
    {"pa", Locale::Language::pa},
    {"pi", Locale::Language::pi},
    {"pl", Locale::Language::pl},
    {"ps", Locale::Language::ps},
    {"pt", Locale::Language::pt},
    {"qu", Locale::Language::qu},
    {"rm", Locale::Language::rm},
    {"rn", Locale::Language::rn},
    {"ro", Locale::Language::ro},
    {"ru", Locale::Language::ru},
    {"rw", Locale::Language::rw},
    {"sa", Locale::Language::sa},
    {"sc", Locale::Language::sc},
    {"sd", Locale::Language::sd},
    {"se", Locale::Language::se},
    {"sg", Locale::Language::sg},
    {"si", Locale::Language::si},
    {"sk", Locale::Language::sk},
    {"sl", Locale::Language::sl},
    {"sm", Locale::Language::sm},
    {"sn", Locale::Language::sn},
    {"so", Locale::Language::so},
    {"sq", Locale::Language::sq},
    {"sr", Locale::Language::sr},
    {"ss", Locale::Language::ss},
    {"st", Locale::Language::st},
    {"su", Locale::Language::su},
    {"sv", Locale::Language::sv},
    {"sw", Locale::Language::sw},
    {"ta", Locale::Language::ta},
    {"te", Locale::Language::te},
    {"tg", Locale::Language::tg},
    {"th", Locale::Language::th},
    {"ti", Locale::Language::ti},
    {"tk", Locale::Language::tk},
    {"tl", Locale::Language::tl},
    {"tn", Locale::Language::tn},
    {"to", Locale::Language::to},
    {"tr", Locale::Language::tr},
    {"ts", Locale::Language::ts},
    {"tt", Locale::Language::tt},
    {"tw", Locale::Language::tw},
    {"ty", Locale::Language::ty},
    {"ug", Locale::Language::ug},
    {"uk", Locale::Language::uk},
    {"ur", Locale::Language::ur},
    {"uz", Locale::Language::uz},
    {"ve", Locale::Language::ve},
    {"vi", Locale::Language::vi},
    {"vo", Locale::Language::vo},
    {"wa", Locale::Language::wa},
    {"wo", Locale::Language::wo},
    {"xh", Locale::Language::xh},
    {"yi", Locale::Language::yi},
    {"yo", Locale::Language::yo},
    {"za", Locale::Language::za},
    {"zh", Locale::Language::zh},
    {"zu", Locale::Language::zu}
  };

std::string Locale::CountryISO2ToString(const Locale::CountryISO2 countryCode)
{
  return sCountryToString[countryCode];
}

Locale::CountryISO2 Locale::CountryISO2FromString(const std::string& countryString,
                                                  bool* resultValid)
{
  std::string countryStringUpperCase = Anki::Util::StringToUpper(countryString);
  auto const& search = sStringToCountry.find(countryStringUpperCase);
  const bool found = search != sStringToCountry.end();
  if (resultValid != nullptr) {
    *resultValid = found;
  }
  if (found) {
    return search->second;
  }
  return kDefaultCountry;
}

std::string Locale::LanguageToString(const Locale::Language languageCode)
{
  return sLanguageToString[languageCode];
}

Locale::Language Locale::LanguageFromString(const std::string& languageString,
                                            bool* resultValid)
{
  std::string languageStringLowerCase = Anki::Util::StringToLower(languageString);
  auto const& search = sStringToLanguage.find(languageStringLowerCase);
  const bool found = search != sStringToLanguage.end();
  if (resultValid != nullptr) {
    *resultValid = found;
  }
  if (found) {
    return search->second;
  }
  return kDefaultLanguage;
}

bool Locale::IsValidLocaleString(const std::string& localeString)
{
  if (localeString.size() != 5) {
    return false;
  }
  bool valid = false;
  std::string languageString = localeString.substr(0, 2);
  (void) Locale::LanguageFromString(languageString, &valid);
  if (!valid) {
    return false;
  }
  std::string countryString = localeString.substr(3, 2);
  (void) Locale::CountryISO2FromString(countryString, &valid);
  return valid;
}

const Locale Locale::kDefaultLocale = Locale(kDefaultLanguage, kDefaultCountry);

Locale Locale::LocaleFromString(const std::string& localeString)
{
  if (localeString.size() != 5) {
    return kDefaultLocale;
  }
  std::string languageString = localeString.substr(0, 2);
  std::string countryString = localeString.substr(3, 2);
  const Locale::Language language = Locale::LanguageFromString(languageString);
  const Locale::CountryISO2 country = Locale::CountryISO2FromString(countryString);
  Locale locale(language, country);
  return locale;
}

// this method will use native adapters to return the current device locale
Locale Locale::GetNativeLocale()
{
#if defined(ANKI_PLATFORM_IOS) || defined(ANKI_PLATFORM_OSX)
  return GetCurrentLocaleIOS();
#elif defined(ANKI_PLATFORM_ANDROID)
  return GetCurrentLocaleAndroid();
#else
  return kDefaultLocale;
#endif
}

std::string Locale::GetLocaleString() const
{
  std::string locale = LanguageToString(_language) + "_" + CountryISO2ToString(_country);
  return locale;
}

std::string Locale::GetLocaleStringLowerCase() const
{
  std::string locale = GetLocaleString();
  return Anki::Util::StringToLower(locale);
}

std::string Locale::GetUrlString() const
{
  std::string str = ToString();
  return Anki::Util::StringToLower(str);
}

std::string Locale::ToString() const
{
  std::string str = LanguageToString(_language) + "-" + CountryISO2ToString(_country);
  return str;
}

} // namespace Util
} // namespace Anki
