# -*- 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.

import sys
from os import path
from calculate.lib.datavars import Variable, VariableError, ReadonlyVariable
from calculate.lib.variables.locale import Locale
from calculate.lib.utils.files import readLinesFile, process
from calculate.lib.utils.portage import isPkgInstalled
from calculate.lib.utils.common import (getValueFromCmdLine, getValueFromConfig,
                                        CmdlineParams, cmpVersion)
from pytz import timezone, country_timezones, UnknownTimeZoneError
from datetime import datetime

from calculate.lib.cl_lang import setLocalTranslate, _

setLocalTranslate('cl_install3', sys.modules[__name__])


class LocaleVariable(ReadonlyVariable, Locale):
    """
    Locale variables not using for flash installation
    """

    def uncompatible(self):
        """
        Network setting up unavailable for flash installation
        """
        if self.Get('os_install_root_type') == 'flash':
            return \
                _("Locale configuration unavailable for Flash install")
        return ""


class VariableOsInstallLinguas(LocaleVariable):
    """
    Current LINGUAS value
    """
    mode = "w"

    def get(self):
        def get_linguas(lines):
            linguas = map(lambda x: x.strip().rpartition('=')[-1].strip('"\''),
                          filter(lambda x: x.startswith("LINGUAS="),
                                 lines))
            return linguas[-1] if linguas else ""

        makeconf = '/etc/make.conf'

        emerge_config = self.Get('cl_emerge_config')
        if emerge_config and "LINGUAS" in emerge_config:
            return emerge_config['LINGUAS'].encode('UTF-8')

        infocommand = ['emerge', '--info']
        defaultLinguas = "bg en de es fr it pl pt_BR nl ru uk"
        # get linguas from make.conf, emerge --info or default
        curlanguage = self.Get('os_install_locale_language')
        return get_linguas(readLinesFile(makeconf)) or \
               " ".join(filter(lambda x: x == "en" or x == curlanguage,
                               get_linguas(
                                   process(
                                       *infocommand).readlines() or "").split())) or \
               defaultLinguas


class VariableOsInstallLocaleConsolefont(LocaleVariable):
    """
    Consolefont for locale
    """

    def get(self):
        return self.getConsolefont(self.Get('os_install_locale_keyboard_layout'))

class VariableOsInstallLocaleKeymap(LocaleVariable):
    """
    Keymap of locale (used for /etc/conf.d/keymaps)
    """

    def get(self):
        return self.getKeymap(self.Get('os_install_locale_keyboard_layout'))


class VariableOsInstallLocaleDumpkeys(LocaleVariable):
    """
    Dumpkeys_charset for keymap
    """

    def get(self):
        # is specified keymap support by locale hash
        if self.Get('os_install_locale_keymap') in self.getFields('keymap'):
            return self.getDumpkeys_charset(
                self.getKeyboardLayout(
                keymap=self.Get('os_install_locale_keymap')))
        else:
            return self.getDumpkeys_charset(
                self.Get('os_install_locale_keyboard_layout'))


class VariableOsInstallLocaleLocale(LocaleVariable):
    """
    Locale (at example: ru_RU.utf8)
    """

    def get(self):
        """locale (example: ru_RU.utf8)"""
        return self.getLocale(self.Get('os_install_locale_lang'))


class VariableOsInstallLocaleLang(LocaleVariable):
    """
    Full language (at example: ru_RU)
    """
    mode = 'w'
    metavalue = "LOCALE"
    type = 'choice'
    opt = ["--locale", "-l"]

    def init(self):
        self.label = _("Locale")
        self.help = _("set the locale")

    def get(self):
        """lang (example: ru_RU)"""
        return self.Get('os_locale_lang')

    def choice(self):
        return zip(self.Get('os_lang'),
                   map(str, self.Get('os_lang', humanreadable=True)))


class VariableOsInstallLocaleKeyboardLayout(LocaleVariable):
    """
    Full language (at example: ru_RU)
    """
    mode = 'w'
    metavalue = "KEYMAP"
    type = 'choice'
    opt = ["--keymap", "-k"]

    def init(self):
        self.label = _("Keyboard layout")
        self.help = _("set the keyboard layout")

    def get(self):
        """lang (example: ru_RU)"""
        selected_lang = self.Get('os_install_locale_lang')
        current_lang = self.Get('os_locale_lang')
        if selected_lang != current_lang:
            return self.getKeyboardLayout(lang=self.Get('os_install_locale_lang'))
        else:
            return self.Get('os_locale_keyboard_layout')

    def choice(self):
        return zip(self.Get('os_keyboard_layout'),
                   map(str, self.Get('os_keyboard_layout', humanreadable=True)))


class VariableOsInstallLocaleLanguage(LocaleVariable):
    """
    Short language (at example ru)
    """

    def get(self):
        return self.getLanguage(self.Get('os_install_locale_lang'))


class VariableOsInstallLocaleXkb(LocaleVariable):
    """
    Keyboard layout for X server
    """

    def get(self):
        return self.getXkblayout(self.Get('os_install_locale_keyboard_layout'))


class VariableOsInstallLocaleXkbname(LocaleVariable):
    """
    Keyboard layout name for X server
    """

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


class VariableOsInstallClockTimezone(LocaleVariable):
    """
    Installation timezone for clock
    """
    mode = 'w'
    type = 'choiceedit'
    metavalue = "TIMEZONE"
    opt = ["--timezone"]
    locale_varname = 'os_install_locale_lang'

    def init(self):
        self.label = _("Timezone")
        self.help = _("set the timezone")

    def get(self):
        return self.Get('os_clock_timezone')

    def check(self, value):
        if not value or not path.isfile(path.join(
                "/usr/share/zoneinfo", value)):
            raise VariableError(_("Wrong timezone %s") % value)

    def generateComments(self, tzs):
        """
        Generate comments by timezone names
        """
        for tzname in tzs:
            # add separator
            if tzname == "---":
                yield ("---", "---")
                continue
            try:
                tz = timezone(tzname)
                strinfo = tz.localize(datetime.now()).strftime('%z')
                yield (
                    tzname, "%s (%s:%s)" % (tzname, strinfo[:3], strinfo[-2:]))
            except UnknownTimeZoneError:
                pass

    def choice(self):
        source = ["Etc/GMT-12",
                  "Pacific/Midway",
                  "Pacific/Honolulu",
                  "America/Anchorage",
                  "Canada/Pacific",
                  "America/Tijuana",
                  "America/Phoenix",
                  "America/Denver",
                  "America/Mazatlan",
                  "America/Monterrey",
                  "America/Regina",
                  "America/Mexico_City",
                  "Canada/Central",
                  "America/Bogota",
                  "America/New_York",
                  "America/Indiana/Indianapolis",
                  "America/Halifax",
                  "America/Caracas",
                  "America/Manaus",
                  "America/Santiago",
                  "America/St_Johns",
                  "America/Sao_Paulo",
                  "America/Argentina/Buenos_Aires",
                  "Etc/GMT+3",
                  "America/Montevideo",
                  "Atlantic/South_Georgia",
                  "Atlantic/Azores",
                  "Atlantic/Cape_Verde",
                  "UTC",
                  "Africa/Casablanca",
                  "Europe/Amsterdam",
                  "Europe/Belgrade",
                  "Europe/Brussels",
                  "Europe/Zagreb",
                  "Africa/Tunis",
                  "Europe/Kaliningrad",
                  "Asia/Amman",
                  "Europe/Athens",
                  "Europe/Istanbul",
                  "Asia/Beirut",
                  "Europe/Helsinki",
                  "Europe/Kiev",
                  "Europe/Sofia",
                  "Africa/Windhoek",
                  "Asia/Jerusalem",
                  "Africa/Cairo",
                  "Europe/Minsk",
                  "Africa/Harare",
                  "Europe/Moscow",
                  "Asia/Baghdad",
                  "Asia/Kuwait",
                  "Africa/Nairobi",
                  "Asia/Tbilisi",
                  "Asia/Tehran",
                  "Europe/Samara",
                  "Asia/Muscat",
                  "Asia/Baku",
                  "Asia/Yerevan",
                  "Asia/Kabul",
                  "Asia/Yekaterinburg",
                  "Asia/Karachi",
                  "Asia/Calcutta",
                  "Asia/Jayapura",
                  "Asia/Katmandu",
                  "Asia/Almaty",
                  "Asia/Omsk",
                  "Asia/Dhaka",
                  "Asia/Rangoon",
                  "Asia/Krasnoyarsk",
                  "Asia/Bangkok",
                  "Asia/Irkutsk",
                  "Asia/Hong_Kong",
                  "Asia/Singapore",
                  "Australia/Perth",
                  "Asia/Taipei",
                  "Asia/Yakutsk",
                  "Asia/Tokyo",
                  "Asia/Seoul",
                  "Australia/Adelaide",
                  "Australia/Darwin",
                  "Asia/Vladivostok",
                  "Australia/Brisbane",
                  "Pacific/Guam",
                  "Australia/Melbourne",
                  "Australia/Hobart",
                  "Asia/Srednekolymsk",
                  "Asia/Kamchatka",
                  "Pacific/Auckland",
                  "Etc/GMT-13"]

        source = list(set(source + Locale().getFields('timezone')))

        def sortkey(s):
            tz = timezone(s)
            strinfo = tz.localize(datetime.now()).strftime('%z')
            return int(strinfo[:3]), int("%s%s" % (strinfo[0], strinfo[-2:]))

        try:
            lang = self.Get(self.locale_varname).split('_')[1]
            nativeTZ = map(lambda x: x.encode('utf-8'),
                           country_timezones[lang])
            source = nativeTZ + ["---"] + \
                     sorted(filter(lambda x: not x in nativeTZ, source),
                            key=sortkey)
        except (KeyError, IndexError) as e:
            pass
        return list(self.generateComments(source))


class VariableOsInstallClockType(Variable):
    """
    Type of clock (UTC or local)
    """
    mode = 'w'
    type = 'choice'
    opt = ["--hwclock"]
    metavalue = "CLOCK"
    fallback_value = "local"

    def init(self):
        self.label = _("Hardware clock type")
        self.help = _("set hardware clock type")

    def exclude_value(self):
        """
        Исключения
        """
        root_type = self.Get('os_root_type')
        hr_virtual = self.Get('hr_virtual')
        # oracle virtualbox по умолчанию для linux систем выставляет
        # использование UTC
        if root_type == "livecd" and hr_virtual == "virtualbox":
            return "UTC"
        return None

    def get(self):
        """type of clock (UTC or local)"""
        # в первую очередь смотрим на параметры загрузки системы
        cmdtype = getValueFromCmdLine(CmdlineParams.Calculate,
                                      CmdlineParams.Clock)
        if cmdtype and cmdtype in self.choice():
            return cmdtype

        # во вторую очередь исключения (например для livecd и virtualbox)
        clocktype = self.exclude_value()
        if clocktype:
            return clocktype

        # получаем значение из конфигурационных файлов hwclock
        clockTypeFile = ['/etc/conf.d/clock', '/etc/conf.d/hwclock']
        for f in clockTypeFile:
            clock = getValueFromConfig(f, "clock")
            if clock:
                if clock.upper() == 'UTC':
                    return clock.upper()
                elif clock.lower() == 'local':
                    return clock.lower()
        # запасное значение
        return self.fallback_value

    def choice(self):
        return ["local", "UTC"]
