/////////////////////////////////////////////////////////////////////////////
// Name:        src/common/languageinfo.cpp
// Purpose:     wxLocale::InitLanguagesDB()
// Author:      Vadim Zeitlin, Vaclav Slavik
// Created:     2010-04-23
// Copyright:   (c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
// Licence:     wxWindows licence
/////////////////////////////////////////////////////////////////////////////

// ============================================================================
// declaration
// ============================================================================

// ----------------------------------------------------------------------------
// headers
// ----------------------------------------------------------------------------

// For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"


#include "wx/intl.h"
#include "wx/uilocale.h"
#include "wx/private/uilocale.h"

#if wxUSE_INTL

#ifdef __WIN32__
    #include "wx/msw/private.h"
#endif

#include <unordered_map>
#include <unordered_set>

// ----------------------------------------------------------------------------
// default languages table & initialization
// ----------------------------------------------------------------------------

// Hash maps to look up language script aliases from script names and vice versa
static std::unordered_map<wxString, wxString> gs_scmap_name2alias;
static std::unordered_map<wxString, wxString> gs_scmap_alias2name;

/* static */ wxString wxUILocaleImpl::GetScriptAliasFromName(const wxString& scriptName)
{
    wxUILocaleImpl::CreateLanguagesDB();
    const auto scIter = gs_scmap_name2alias.find(scriptName);
    if (scIter != gs_scmap_name2alias.end())
        return scIter->second;
    else
        return wxString();
}

/* static */ wxString wxUILocaleImpl::GetScriptNameFromAlias(const wxString& scriptAlias)
{
    wxUILocaleImpl::CreateLanguagesDB();
    const auto scIter = gs_scmap_alias2name.find(scriptAlias);
    if (scIter != gs_scmap_alias2name.end())
        return scIter->second;
    else
        return wxString();
}

// Hash map to look up likely subtags
static std::unordered_map<wxString, wxString> gs_likely_subtags_map;

/* static */ wxString wxUILocaleImpl::GetLikelySubtags(const wxString& fromTag)
{
    wxUILocaleImpl::CreateLanguagesDB();
    const auto tagIter = gs_likely_subtags_map.find(fromTag);
    if (tagIter != gs_likely_subtags_map.end())
        return tagIter->second;
    else
        return wxString();
}

// Hash map to look up distances for matching tag pairs
static std::unordered_map<wxString, int> gs_matching_tags_map;

/* static */ int wxUILocaleImpl::GetMatchDistance(const wxString& desiredTag, const wxString& supportedTag)
{
    wxUILocaleImpl::CreateLanguagesDB();
    const auto tagIter = gs_matching_tags_map.find(desiredTag+wxString(":")+supportedTag);
    if (tagIter != gs_matching_tags_map.end())
        return tagIter->second;
    else
        return -1;
}

// Hash map to look up distances for matching tag pairs
static std::unordered_map<wxString, std::unordered_set<wxString>> gs_region_groups_map;

/* static */ bool wxUILocaleImpl::SameRegionGroup(const wxString& language, const wxString& desiredRegion, const wxString& supportedRegion)
{
    wxUILocaleImpl::CreateLanguagesDB();
    const auto languageIter = gs_region_groups_map.find(language);
    if (languageIter != gs_region_groups_map.end())
    {
        const auto groupSet = languageIter->second;
        bool containsDesired = groupSet.find(desiredRegion) != groupSet.end();
        bool containsSupported = groupSet.find(supportedRegion) != groupSet.end();
        // Desired region and supported region belong to the same region group,
        // if they are either both contained or both not contained in the region group.
        return (containsDesired && containsSupported) || (!containsDesired && !containsSupported);
    }

    return false;
}

// --- --- --- generated code begins here --- --- ---

// The following data tables are generated by misc/languages/genlang.py
// When making changes, please put them into misc/languages/langtabl.txt

#if !defined(__WIN32__)

#define SETWINLANG(info,lang,sublang)

#else

#define SETWINLANG(info,lang,sublang) \
    info.WinLang = tabLangData[j].lang; \
    info.WinSublang = tabLangData[j].sublang;

#endif // __WIN32__

// Include actual data tables
#include "wx/private/lang_info.h"
#include "wx/private/lang_scripts.h"
#include "wx/private/lang_likely.h"
#include "wx/private/lang_match.h"
#include "wx/private/lang_regions.h"

void wxUILocaleImpl::InitLanguagesDB()
{
    wxLanguageInfo info;
    int j;

    // Known languages
    for (j = 0; tabLangData[j].wxlang != 0; ++j)
    {
        info.Language = tabLangData[j].wxlang;
        info.LocaleTag = tabLangData[j].bcp47tag;
        info.CanonicalName = tabLangData[j].canonical;
        info.CanonicalRef = tabLangData[j].canonicalref;
        info.LayoutDirection = tabLangData[j].layout;
        info.Description = wxString::FromUTF8(tabLangData[j].desc);
        info.DescriptionNative = wxString::FromUTF8(tabLangData[j].descnative);
        SETWINLANG(info, winlang, winsublang)
        wxUILocale::AddLanguage(info);
    }

    // Known language scripts
    for (j = 0; tabScriptData[j].scname; ++j)
    {
        gs_scmap_name2alias[tabScriptData[j].scname] = tabScriptData[j].scalias;
        gs_scmap_alias2name[tabScriptData[j].scalias] = tabScriptData[j].scname;
    }

    // Known likely subtags
    for (j = 0; tabLikelyData[j].tagfrom; ++j)
    {
        gs_likely_subtags_map[tabLikelyData[j].tagfrom] = tabLikelyData[j].tagto;
    }

    // Known matching language tags
    for (j = 0; tabMatchData[j].matchkey; ++j)
    {
        gs_matching_tags_map[tabMatchData[j].matchkey] = tabMatchData[j].matchval;
    }

    // Known region groups
    wxString langPrev;
    wxString lang;
    std::unordered_set<wxString>* regionGroup = nullptr;
    for (j = 0; regionGroupData[j].language; ++j)
    {
        lang = regionGroupData[j].language;
        if (!langPrev.IsSameAs(lang))
        {
            langPrev = lang;
            gs_region_groups_map[lang] = std::unordered_set<wxString>();
            regionGroup = &gs_region_groups_map[lang];
        }
        regionGroup->insert(regionGroupData[j].country);
    }
}

// --- --- --- generated code ends here --- --- ---

#endif // wxUSE_INTL
