# -*- coding: utf-8 -*-

# Copyright 2008-2016 Mir Calculate. http://www.calculate-linux.org
#
#  Licensed under the Apache License, Version 2.0 (the "License");
#  you may not use this file except in compliance with the License.
#  You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
#  Unless required by applicable law or agreed to in writing, software
#  distributed under the License is distributed on an "AS IS" BASIS,
#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#  See the License for the specific language governing permissions and
#  limitations under the License.

from os import path
import os
from calculate.lib.datavars import ReadonlyVariable
from calculate.lib.utils.common import (getValueFromCmdLine,
                                        getValueFromConfig, CmdlineParams)
from collections import OrderedDict

import sys
from calculate.lib.cl_lang import setLocalTranslate, getLazyLocalTranslate

_ = lambda x: x
setLocalTranslate('cl_lib3', sys.modules[__name__])

__ = getLazyLocalTranslate(_)


class Locale(object):
    # http://www.localeplanet.com/icu/
    langData = OrderedDict([
        ('be_BY', {
            'name': 'Беларуская (Беларусь)',
            'locale': 'be_BY.utf8',
            'keymap': 'by',
            'timezone': 'Europe/Minsk',
            'dumpkeys_charset': 'koi8-u',
            'consolefont': 'ter-v14n',
            'xkblayout': 'us,by',
            'language': 'be',
        }),
        ('bg_BG', {
            'name': 'Български (България)',
            'locale': 'bg_BG.utf8',
            'keymap': 'bg_bds-utf8',
            'dumpkeys_charset': '',
            'timezone': 'Europe/Sofia',
            'consolefont': 'ter-v14n',
            'xkblayout': 'us,bg',
            'language': 'bg',
        }),
        ('bs_BA', {
            'name': 'Bosanski (Bosna i Hercegovina)',
            'locale': 'bs_BA.utf8',
            'keymap': 'slovene',
            'timezone': 'Europe/Sarajevo',
            'dumpkeys_charset': '',
            'consolefont': 'ter-v14n',
            'xkblayout': 'ba',
            'language': 'bs',
        }),
        ('cs_CZ', {
            'name': 'Čeština (Česká republika)',
            'locale': 'cs_CZ.utf8',
            'keymap': 'cz',
            'timezone': 'Europe/Prague',
            'dumpkeys_charset': '',
            'consolefont': 'ter-v14n',
            'xkblayout': 'cz',
            'language': 'cs',
        }),
        ('da_DK', {
            'name': 'Dansk (Danmark)',
            'locale': 'da_DK.utf8',
            'keymap': 'dk-latin1',
            'timezone': 'Europe/Copenhagen',
            'dumpkeys_charset': '',
            'consolefont': 'ter-v14n',
            'xkblayout': 'dk',
            'language': 'da',
        }),
        ('de_DE', {
            'name': 'Deutsch (Deutschland)',
            'locale': 'de_DE.utf8',
            'keymap': 'de-latin1',
            'timezone': 'Europe/Berlin',
            'dumpkeys_charset': '',
            'consolefont': 'ter-v14n',
            'xkblayout': 'de',
            'language': 'de',
        }),
        ('en_AU', {
            'name': 'English (Australia)',
            'locale': 'en_AU.utf8',
            'keymap': 'us',
            'timezone': 'Australia/Canberra',
            'dumpkeys_charset': '',
            'consolefont': 'ter-v14n',
            'xkblayout': 'us',
            'language': 'en_AU',
        }),
        ('en_GB', {
            'name': 'English (United Kingdom)',
            'locale': 'en_GB.utf8',
            'keymap': 'uk',
            'timezone': 'Europe/London',
            'dumpkeys_charset': '',
            'consolefont': 'ter-v14n',
            'xkblayout': 'gb',
            'language': 'en_GB',
        }),
        ('en_US', {
            'name': 'English (United States)',
            'locale': 'en_US.utf8',
            'keymap': 'us',
            'timezone': 'America/New_York',
            'dumpkeys_charset': '',
            'consolefont': 'ter-v14n',
            'xkblayout': 'us',
            'language': 'en',
        }),
        ('es_ES', {
            'name': 'Español (España)',
            'locale': 'es_ES.utf8',
            'keymap': 'es euro2',
            'timezone': 'Europe/Madrid',
            'dumpkeys_charset': '',
            'consolefont': 'ter-v14n',
            'xkblayout': 'es',
            'language': 'es',
        }),
        ('es_UY', {
            'name': 'Español (Uruguay)',
            'locale': 'es_UY.utf8',
            'keymap': 'la-latin1',
            'timezone': 'America/Montevideo',
            'dumpkeys_charset': '',
            'consolefont': 'ter-v14n',
            'xkblayout': 'latam',
            'language': 'es_UY',
        }),
        ('es_VE', {
            'name': 'Español (Venezuela)',
            'locale': 'es_VE.utf8',
            'keymap': 'la-latin1',
            'timezone': 'America/Caracas',
            'dumpkeys_charset': '',
            'consolefont': 'ter-v14n',
            'xkblayout': 'latam',
            'language': 'es_UY',
        }),
        ('et_EE', {
            'name': 'Eesti (Eesti)',
            'locale': 'et_EE.utf8',
            'keymap': 'et',
            'timezone': 'Europe/Tallinn',
            'dumpkeys_charset': '',
            'consolefont': 'ter-v14n',
            'xkblayout': 'ee',
            'language': 'et',
        }),
        ('fr_BE', {
            'name': 'Français (Belgique)',
            'locale': 'fr_BE.utf8',
            'keymap': 'be-latin1',
            'timezone': 'Europe/Brussels',
            'dumpkeys_charset': '',
            'consolefont': 'ter-v14n',
            'xkblayout': 'be',
            'language': 'fr',
        }),
        ('fr_CA', {
            'name': 'Français (Canada)',
            'locale': 'fr_CA.utf8',
            'keymap': 'cf',
            'timezone': 'Canada/Pacific',
            'dumpkeys_charset': '',
            'consolefont': 'ter-v14n',
            'xkblayout': 'ca',
            'language': 'fr',
        }),
        ('fr_FR', {
            'name': 'Français (France)',
            'locale': 'fr_FR.utf8',
            'keymap': 'fr-latin9',
            'timezone': 'Europe/Paris',
            'dumpkeys_charset': '',
            'consolefont': 'ter-v14n',
            'xkblayout': 'fr',
            'language': 'fr',
        }),
        ('hr_HR', {
            'name': 'Hrvatski (Hrvatska)',
            'locale': 'hr_HR.utf8',
            'keymap': 'croat',
            'timezone': 'Europe/Zagreb',
            'dumpkeys_charset': '',
            'consolefont': 'ter-v14n',
            'xkblayout': 'hr',
            'language': 'hr',
        }),
        ('is_IS', {
            'name': 'Íslenska (Ísland)',
            'locale': 'is_IS.utf8',
            'keymap': 'is-latin1',
            'timezone': 'Atlantic/Reykjavik',
            'dumpkeys_charset': '',
            'consolefont': 'ter-v14n',
            'xkblayout': 'is',
            'language': 'is',
        }),
        ('it_IT', {
            'name': 'Italiano (Italia)',
            'locale': 'it_IT.utf8',
            'keymap': 'it',
            'dumpkeys_charset': '',
            'timezone': 'Europe/Rome',
            'consolefont': 'ter-v14n',
            'xkblayout': 'it',
            'language': 'it',
        }),
        ('kk_KZ', {
            'name': 'Қазақ тілі (Қазақстан)',
            'locale': 'kk_KZ.utf8',
            'keymap': 'kaz_gost-unicode',
            'timezone': 'Asia/Almaty',
            'dumpkeys_charset': '',
            'consolefont': 'ter-v14n',
            'xkblayout': 'us,kz',
            'language': 'kk',
        }),
        ('lt_LT', {
            'name': 'Lietuvių (Lietuva)',
            'locale': 'lt_LT.utf8',
            'keymap': 'lt.baltic',
            'timezone': 'Europe/Vilnius',
            'dumpkeys_charset': '',
            'consolefont': 'ter-v14n',
            'xkblayout': 'lt',
            'language': 'lt',
        }),
        ('lv_LV', {
            'name': 'Latviešu (Latvija)',
            'locale': 'lv_LV.utf8',
            'keymap': 'lv',
            'timezone': 'Europe/Riga',
            'dumpkeys_charset': '',
            'consolefont': 'ter-v14n',
            'xkblayout': 'lv',
            'language': 'lv',
        }),
        ('hu_HU', {
            'name': 'Magyar (Magyarország)',
            'locale': 'hu_HU.utf8',
            'keymap': 'hu',
            'timezone': 'Europe/Budapest',
            'dumpkeys_charset': '',
            'consolefont': 'ter-v14n',
            'xkblayout': 'hu',
            'language': 'hu',
        }),
        ('nl_BE', {
            'name': 'Nederlands (België)',
            'locale': 'nl_BE.utf8',
            'keymap': 'nl',
            'timezone': 'Europe/Brussels',
            'dumpkeys_charset': '',
            'consolefont': 'lat9w-16',
            'xkblayout': 'nl',
            'language': 'nl_BE',
        }),
        ('nl_NL', {
            'name': 'Nederlands (Nederland)',
            'locale': 'nl_NL.utf8',
            'keymap': 'nl',
            'timezone': 'Europe/Amsterdam',
            'dumpkeys_charset': '',
            'consolefont': 'ter-v14n',
            'xkblayout': 'nl',
            'language': 'nl_NL',
        }),
        ('nn_NO', {
            'name': 'Nynorsk (Noreg)',
            'locale': 'nn_NO.utf8',
            'keymap': 'no-latin1',
            'timezone': 'Europe/Oslo',
            'dumpkeys_charset': '',
            'consolefont': 'ter-v14n',
            'xkblayout': 'no',
            'language': 'nn',
        }),
        ('pl_PL', {
            'name': 'Polski (Polska)',
            'locale': 'pl_PL.utf8',
            'keymap': 'pl',
            'timezone': 'Europe/Warsaw',
            'dumpkeys_charset': '',
            'consolefont': 'ter-v14n',
            'xkblayout': 'pl',
            'language': 'pl',
        }),
        ('pt_BR', {
            'name': 'Português (Brasil)',
            'locale': 'pt_BR.utf8',
            'keymap': 'br-abnt2',
            'timezone': 'Brazil/East',
            'dumpkeys_charset': '',
            'consolefont': 'ter-v14n',
            'xkblayout': 'br',
            'language': 'pt_BR',
        }),
        ('pt_PT', {
            'name': 'Português (Portugal)',
            'locale': 'pt_PT.utf8@euro',
            'keymap': 'pt-latin9',
            'dumpkeys_charset': '',
            'timezone': 'Europe/Lisbon',
            'consolefont': 'ter-v14n',
            'xkblayout': 'pt',
            'language': 'pt',
        }),
        ('ro_RO', {
            'name': 'Română (România)',
            'locale': 'ro_RO.utf8',
            'keymap': 'ro_win',
            'timezone': 'Europe/Bucharest',
            'dumpkeys_charset': '',
            'consolefont': 'ter-v14n',
            'xkblayout': 'ro',
            'language': 'ro',
        }),
        ('ru_RU', {
            'name': 'Русский (Россия)',
            'locale': 'ru_RU.utf8',
            'keymap': '-u ruwin_cplk-UTF-8',
            'timezone': 'Europe/Moscow',
            'dumpkeys_charset': '',
            'consolefont': 'ter-v14n',
            'xkblayout': 'us,ru',
            'language': 'ru',
        }),
        ('sk_SK', {
            'name': 'Slovenčina (Slovenská republika)',
            'locale': 'sk_SK.utf8',
            'keymap': 'sk-qwertz',
            'dumpkeys_charset': '',
            'timezone': 'Europe/Bratislava',
            'consolefont': 'ter-v14n',
            'xkblayout': 'sk',
            'language': 'sk',
        }),
        ('sl_SI', {
            'name': 'Slovenščina (Slovenija)',
            'locale': 'sl_SI.utf8',
            'keymap': 'slovene',
            'timezone': 'Europe/Ljubljana',
            'dumpkeys_charset': '',
            'consolefont': 'ter-v14n',
            'xkblayout': 'si',
            'language': 'sl',
        }),
        ('sq_AL', {
            'name': 'Shqip (Shqipëria)',
            'locale': 'sq_AL.utf8',
            'keymap': 'al',
            'timezone': 'Europe/Tirane',
            'dumpkeys_charset': '',
            'consolefont': 'ter-v14n',
            'xkblayout': 'al',
            'language': 'sq',
        }),
        ('sr_RS', {
            'name': 'Српски (Србија)',
            'locale': 'sr_RS.utf8',
            'keymap': 'sr-unicode',
            'timezone': 'Europe/Belgrade',
            'dumpkeys_charset': '',
            'consolefont': 'ter-v14n',
            'xkblayout': 'us,rs',
            'language': 'sr',
        }),
        ('fi_FI', {
            'name': 'Suomi (Suomi)',
            'locale': 'fi_FI.utf8',
            'keymap': 'fi',
            'timezone': 'Europe/Helsinki',
            'dumpkeys_charset': '',
            'consolefont': 'ter-v14n',
            'xkblayout': 'fi',
            'language': 'fi',
        }),
        ('sv_SE', {
            'name': 'Svenska (Sverige)',
            'locale': 'sv_SE.utf8',
            'keymap': 'sv-latin1',
            'timezone': 'Europe/Stockholm',
            'dumpkeys_charset': '',
            'consolefont': 'lat0-16',
            'xkblayout': 'us,se',
            'language': 'sv',
        }),
        ('uk_UA', {
            'name': 'Українська (Україна)',
            'locale': 'uk_UA.utf8',
            'keymap': 'ua-utf',
            'timezone': 'Europe/Kiev',
            'dumpkeys_charset': 'koi8-u',
            'consolefont': 'ter-v14n',
            'xkblayout': 'us,ua',
            'language': 'ua',
        })
    ])

    def getLangs(self):
        return self.langData.keys()

    def getLanguages(self):
        return map(lambda x: self.langData[x]['language'],
                   self.langData.keys())

    def isLangExists(self, lang):
        return lang in self.langData.keys()

    def isValueInFieldExists(self, field, value):
        return value in map(lambda x: self.langData[x][field],
                            self.langData.keys())

    def getFields(self, field):
        return [l[1][field] for l in self.langData.items()]

    def getFieldByLang(self, field, lang):
        return self.langData.get(lang, self.langData['en_US'])[field]

    def getFieldByKeymap(self, field, keymap):
        return self.langData.get(self.getLangByField('keymap', keymap),
                                 self.langData['en_US'])[field]

    def getLangByField(self, field, value):
        value = value or ""
        if field == 'locale':
            value = (value,value.replace('UTF-8','utf8'))
        else:
            value = (value,)

        langs = [lang[0] for lang in self.langData.items()
                 if lang[1][field] in value]
        if not langs:
            return 'en_US'
        else:
            return langs[0]


class VariableOsClockTimezone(ReadonlyVariable):
    """
    Current timezone
    """

    def get(self):
        zoneinfodir = "/usr/share/zoneinfo/"
        timezonefile = "/etc/timezone"
        # try get timezone from kernel calculate param
        timezone = getValueFromCmdLine(
            CmdlineParams.Calculate, CmdlineParams.Timezone)
        if timezone and \
                path.exists(path.join(zoneinfodir, timezone)):
            return timezone
        # get timezone from /etc/timezone
        if path.exists(timezonefile):
            return open(timezonefile, "r").read().strip()
        return "UTC"


class VariableOsLocaleLocale(ReadonlyVariable, Locale):
    """
    Locale (example: ru_RU.utf8)
    """
    env_var = "LANG"

    def get(self):
        # get locale from boot calculate param
        locale_file = '/etc/env.d/02locale'
        locale_val = getValueFromCmdLine(
            CmdlineParams.Calculate, CmdlineParams.Locale)
        if self.isLangExists(locale_val):
            cmd_val = self.getFieldByLang('locale', locale_val)
        else:
            cmd_val = None
        locale_val = getValueFromConfig(locale_file, self.env_var) or ""
        locale_val = locale_val.replace('UTF-8','utf8')
        if self.isValueInFieldExists('locale', locale_val):
            file_val = locale_val
        else:
            file_val = None
        if file_val or cmd_val:
            if self.GetBool('cl_system_boot_set'):
                return cmd_val or file_val
            else:
                return file_val or cmd_val
        if self.env_var in os.environ and os.environ[self.env_var] != "C":
            return os.environ[self.env_var]
        return self.getFieldByLang("locale", "default")


class VariableOsLocaleLang(ReadonlyVariable, Locale):
    """
    Language (example: ru_RU)
    """

    def get(self):
        """lang (example: ru_RU)"""
        return self.getLangByField("locale", self.Get('os_locale_locale'))


class VariableOsLocaleLanguage(ReadonlyVariable, Locale):
    """
    Short lang name (example: ru)
    """

    def get(self):
        return self.getFieldByLang("language", self.Get('os_locale_lang'))


class VariableOsLocaleXkb(ReadonlyVariable, Locale):
    """
    Keyboard layout for X server (example: us,ru)
    """

    def get(self):
        """xkb layouts (example: en,ru)"""
        return self.getFieldByLang("xkblayout", self.Get('os_locale_lang'))


class VariableOsLocaleXkbname(ReadonlyVariable, Locale):
    """
    Keyboard layout name for X server (remove value in hooks)
    """

    def get(self):
        locale_xkb = self.Get("os_locale_xkb")
        if locale_xkb:
            return locale_xkb.split("(")[0]
        return ""


class VariableOsLocaleLatSet(ReadonlyVariable, Locale):
    """
    Локаль содержит раскладку совместимую с латиницей

    Используется для отображения индикатора переключения языка
    """

    def get(self):
        """xkb layouts (example: en,ru)"""
        layout = self.Get('os_locale_xkbname').split(',')
        if len(layout) == 1:
            return self.On
        else:
            return self.Off


class VariableOsLang(ReadonlyVariable, Locale):
    """
    Supported langs
    """
    type = "list"

    def get(self):
        return self.getLangs()

    def humanReadable(self):
        return map(lambda x: self.getFieldByLang("name", x),
                   self.Get())
