from __future__ import unicode_literals
from future import standard_library
standard_library.install_aliases()
from builtins import zip
from builtins import str
import builtins
import os
import sys
import ctypes
import locale
import gettext
import paths
import platform
import application

#a few Windows locale constants
LOCALE_SLANGUAGE=0x2
LOCALE_SLANGDISPLAYNAME=0x6f

curLang="en"

def localeNameToWindowsLCID(localeName):
    """Retreave the Windows locale identifier (LCID) for the given locale name
    @param localeName: a string of 2letterLanguage_2letterCountry or or just 2letterLanguage
    @type localeName: string
    @returns: a Windows LCID
    @rtype: integer
    """ 
    #Windows Vista is able to convert locale names to LCIDs
    func_LocaleNameToLCID=getattr(ctypes.windll.kernel32,'LocaleNameToLCID',None)
    if func_LocaleNameToLCID is not None:
        localeName=localeName.replace('_','-')
        LCID=func_LocaleNameToLCID(str(localeName),0)
    else: #Windows doesn't have this functionality, manually search Python's windows_locale dictionary for the LCID
        localeName=locale.normalize(localeName)
        if '.' in localeName:
            localeName=localeName.split('.')[0]
        LCList=[x[0] for x in locale.windows_locale.items() if x[1]==localeName]
        if len(LCList)>0:
            LCID=LCList[0]
        else:
            LCID=0
    return LCID

def getLanguageDescription(language):
    """Finds out the description (localized full name) of a given local name"""
    desc=None
    if platform.system() == "Windows":
        LCID=localeNameToWindowsLCID(language)
        if LCID!=0:
            buf=ctypes.create_unicode_buffer(1024)
            if '_' not in language:
                res=ctypes.windll.kernel32.GetLocaleInfoW(LCID,LOCALE_SLANGDISPLAYNAME,buf,1024)
            else:
                res=0
            if res==0:
                res=ctypes.windll.kernel32.GetLocaleInfoW(LCID,LOCALE_SLANGUAGE,buf,1024)
            desc=buf.value
    elif platform.system() == "Linux" or not desc:
        desc={
            "am":pgettext("languageName","Amharic"),
            "an":pgettext("languageName","Aragonese"),
            "es":pgettext("languageName","Spanish"),
            "pt":pgettext("languageName","Portuguese"),
            "ru":pgettext("languageName","Russian"),
            "it":pgettext("languageName","italian"),
            "tr":pgettext("languageName","Turkey"),
            "gl":pgettext("languageName","Galician"),
            "ca":pgettext("languageName","Catala"),
            "eu":pgettext("languageName","Vasque"),
            "pl":pgettext("languageName","polish"),
            "ar":pgettext("languageName","Arabic"),
            "ne":pgettext("languageName","Nepali"),
            "sr":pgettext("languageName","Serbian (Latin)"),
            "ja":pgettext("languageName","Japanese"),
        }.get(language,None)
    return desc

def getAvailableLanguages():
    """generates a list of locale names, plus their full localized language and country names.
    @rtype: list of tuples
    """
    #Make a list of all the locales found in NVDA's locale dir
    l=[x for x in os.listdir(paths.locale_path()) if not x.startswith('.')]
    l=[x for x in l if os.path.isfile(os.path.join(paths.locale_path(), '%s/LC_MESSAGES/%s.po' % (x, application.short_name)))]
    #Make sure that en (english) is in the list as it may not have any locale files, but is default
    if 'en' not in l:
        l.append('en')
        l.sort()
    #For each locale, ask Windows for its human readable display name
    d=[]
    for i in l:
        desc=getLanguageDescription(i)
        label="%s, %s"%(desc,i) if desc else i
        d.append(label)
    #include a 'user default, windows' language, which just represents the default language for this user account
    l.append("system")
    # Translators: the label for the Windows default NVDA interface language.
    d.append(_("User default"))
    #return a zipped up version of both the lists (a list with tuples of locale,label)
    return list(zip(l,d))

def makePgettext(translations):
    """Obtaina  pgettext function for use with a gettext translations instance.
    pgettext is used to support message contexts,
    but Python 2.7's gettext module doesn't support this,
    so NVDA must provide its own implementation.
    """
    if isinstance(translations, gettext.GNUTranslations):
        def pgettext(context, message):
            message = str(message)
            try:
                # Look up the message with its context.
                return translations._catalog["%s\x04%s" % (context, message)]
            except KeyError:
                return message
    else:
        def pgettext(context, message):
            return str(message)
    return pgettext

def setLanguage(lang):
    system = platform.system()
    global curLang
    try:
        if lang=="system":
            if system == "Windows":
                windowsLCID=ctypes.windll.kernel32.GetUserDefaultUILanguage()
                localeName=locale.windows_locale[windowsLCID]
            elif system == "Darwin":
                import Foundation
                localeName = Foundation.NSLocale.currentLocale().identifier()
            elif system == "Linux":
                localeName = locale.getdefaultlocale()[0]
            trans=gettext.translation(application.short_name, localedir=paths.locale_path(), languages=[localeName])
            curLang=localeName
#			else:
#				localeName=locale.getdefaultlocale()[0]
#			trans=gettext.translation('twblue', localedir=paths.locale_path(), languages=[localeName])
#			curLang=localeName

        else:
            trans=gettext.translation(application.short_name, localedir=paths.locale_path(), languages=[lang])
            curLang=lang
            localeChanged=False
            #Try setting Python's locale to lang
#			try:
            if system == "Windows":
                locale.setlocale(locale.LC_ALL, langToWindowsLocale(lang))
                localeChanged=True
            else:
                locale.setlocale(locale.LC_ALL, lang)
                localeChanged=True
#			except:
#				pass
            if not localeChanged and '_' in lang:
                #Python couldn'tsupport the language_country locale, just try language.
                try:
                    locale.setlocale(locale.LC_ALL, lang.split('_')[0])
                except:
                    pass
            #Set the windows locale for this thread (NVDA core) to this locale.
            if system == "Windows":
                LCID=localeNameToWindowsLCID(lang)
                ctypes.windll.kernel32.SetThreadLocale(LCID)
    except IOError:
        trans=gettext.translation(application.short_name, fallback=True)
        curLang="en"
    if sys.version[0] == "3":
        trans.install()
    else:
        trans.install(unicode=True)
    # Install our pgettext function.
#	__builtin__.__dict__["pgettext"] = makePgettext(trans)

def getLanguage():
    return curLang

def normalizeLanguage(lang):
    """
    Normalizes a  language-dialect string  in to a standard form we can deal with.
    Converts  any dash to underline, and makes sure that language is lowercase and dialect is upercase.
    """
    lang=lang.replace('-','_')
    ld=lang.split('_')
    ld[0]=ld[0].lower()
    #Filter out meta languages such as x-western
    if ld[0]=='x':
        return None
    if len(ld)>=2:
        ld[1]=ld[1].upper()
    return "_".join(ld)

def langToWindowsLocale(lang):
    languages = {"en": "eng",
                 "ar": "ara",
                 "ca": "cat",
                 "de": "deu",
                 "es": "esp",
                 "fi": "fin",
                 "fr": "fre_FRA",
                 "gl": "glc",
                 "eu": "euq",
                 "hu": "hun",
                 "hr": "hrv",
                 "it": "ita",
                 "ja": "jpn",
                 "pl": "plk",
                 "pt": "ptb",
                 "ru": "rus",
                 "tr": "trk",
                 "sr": "eng",
                 }
    return languages[lang]
