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

# Copyright 2008-2013 Calculate Ltd. 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 os
import gettext
from gettext import gettext as _
import threading
import types
import sys
import re
from gettext import Catalog



class lang:
    """
    Multilanguage class
    """
    _modnames = {}
    GP = [""]

    def __init__(self):
        self.nameDomain = self.GP[0]
        self.__catalog = None
        # translate language for all modules
        self._translators = {}

    def __translate(self,message):
        """Method return message without changes"""
        return self.__gettranslate()(message)

    def setLanguage(self,module,glob=False):
        """Set translate language for modules 'module'.

            module - export python module
            if the module export other modules, then lang will be
            set for them
            Method must be call after module for translate"""
        if glob:
            for name,mod in vars(module).items():
                if type(mod) == types.ModuleType and \
                        not name.startswith('__') and \
                        not name in sys.builtin_module_names and \
                        (hasattr(mod, '__file__') and (
                                        "calculate" in mod.__file__ or
                                    not mod.__file__.startswith('/usr/lib'))):
                    self.__setLang(mod)
                    self.setLanguage(mod, True)
        return self.__setLang(module)

    def __setLang(self,module):
        """ Set translate language for module 'module'.
        """
        if module.__name__ in self._modnames.keys():
            return True

        module._ = self.__translate
        self._modnames[module.__name__] = module._


    @staticmethod
    def get_current_lang():
        """
        Получить текущий язык
        """
        env = os.environ
        cur_thread = threading.currentThread()
        if hasattr(cur_thread, "lang"):
            return cur_thread.lang
        return env.get("LANG", "en_US.UTF-8").split('.')[0].split("_")[0]

    def __gettranslate(self):
        l = self.get_current_lang()
        if l in self._translators:
            return self._translators[l]
        if l == 'en':
            trans = lambda x:x
        else:
            la = [l]
            reload(gettext)
            if gettext.find(self.nameDomain,self.__catalog,la):
                """Если найден словарь то инициализируем переводчик"""
                transl = gettext.translation(self.nameDomain,self.__catalog,la)
                trans = transl.gettext
            else:
                trans = lambda x:x
        self._translators[l] = trans
        return trans

    def getTranslatorByName(self,namemodule):
        """Method for detect already imported translate modules
        """
        if self._modnames.has_key(namemodule):
            return self._modnames[namemodule]
        return 0

    def setGlobalDomain(self, nameDomain):
        """ Method for set global translate domain
        """
        self.GP[0] = nameDomain
        self.nameDomain = self.GP[0]
        return True

    def setLocalDomain(self, nameDomain):
        """ Method for set local translate domain
        """
        self.nameDomain = nameDomain
        return True
 
def setGlobalTranslate(domain,*modules):
    _lang = lang()
    _lang.setGlobalDomain(domain)
    for mod in modules:
        _lang.setLanguage(mod,glob=True)

def setLocalTranslate(domain,*modules):
    _lang = lang()
    _lang.setLocalDomain(domain)
    for mod in modules:
        _lang.setLanguage(mod)

def getLazyLocalTranslate(translateFunc):
    class translate:
        def __init__(self,s):
            self.s = s
            self._format_args = None

        def __str__(self):
            if self._format_args is None:
                return translateFunc(self.s)
            else:
                return translateFunc(self.s).format(*self._format_args[0],
                                                   **self._format_args[1])
        def __hash__(self):
            return hash(self.s)

        def format(self, *args, **kwargs):
            self._format_args = (args,kwargs)
            return self

    return translate


class RegexpLocalization(object):
    def __init__(self, domain, languages=[lang.get_current_lang()]):
        try:
            self.set_translate_dict(Catalog(domain,
                                            languages=languages)._catalog)
        except IOError:
            self._catalog = {}

    def set_translate_dict(self, d):
        def create_key(k):
            try:
                return re.compile(k.replace("\\\\", "\\"))
            except re.error:
                return None

        self._catalog = filter(lambda x: x[0],
                               ((create_key(k), v) for k, v in
                                sorted(d.items(), reverse=True) if k))

    def translate(self, s):
        for k, v in self._catalog:
            try:
                s = k.sub(v, s)
            except UnicodeDecodeError:
                return s
        return s
