import gettext
import os
import sys

from kivy._event import Observable

from katrain.core.utils import find_package_resource
from katrain.gui.style import DEFAULT_FONT


class Lang(Observable):
    observers = []
    callbacks = []
    FONTS = {
        "ko": "fonts/NotoSansKR-Regular.otf",
        "cn": "fonts/NotoSansCJKsc-Regular.otf",
        "jp": "fonts/NotoSansJP-Regular.otf",
    }

    def __init__(self, lang):
        super(Lang, self).__init__()
        self.lang = None
        self.switch_lang(lang)

    def _(self, text):
        return self.ugettext(text)

    def set_widget_font(self, widget):
        widget.font_name = self.font_name
        for sub_widget in [getattr(widget, "_hint_lbl", None), getattr(widget, "_msg_lbl", None)]:  # MDText
            if sub_widget:
                sub_widget.font_name = self.font_name

    def fbind(self, name, func, *args):
        if name == "_":
            widget, property, *_ = args[0]
            self.observers.append((widget, func, args))
            try:
                self.set_widget_font(widget)
            except Exception as e:
                print(e)
                # pass
        else:
            return super(Lang, self).fbind(name, func, *args)

    def funbind(self, name, func, *args):
        if name == "_":
            widget, *_ = args[0]
            key = (widget, func, args)
            if key in self.observers:
                self.observers.remove(key)
        else:
            return super(Lang, self).funbind(name, func, *args)

    def switch_lang(self, lang):
        if lang == self.lang:
            return
        # get the right locales directory, and instantiate a gettext
        self.lang = lang
        self.font_name = self.FONTS.get(lang) or DEFAULT_FONT
        i18n_dir, _ = os.path.split(find_package_resource("katrain/i18n/__init__.py"))
        locale_dir = os.path.join(i18n_dir, "locales")
        locales = gettext.translation("katrain", locale_dir, languages=[lang, DEFAULT_LANGUAGE])
        self.ugettext = locales.gettext

        # update all the kv rules attached to this text
        for widget, func, args in self.observers:
            try:
                func(args[0], None, None)
                self.set_widget_font(widget)
            except ReferenceError:
                pass  # proxy no longer exists
            except Exception as e:
                print("Error in switching languages", e)
        for cb in self.callbacks:
            try:
                cb(self)
            except Exception as e:
                print(f"Failed callback on language change: {e}", file=sys.stderr)


DEFAULT_LANGUAGE = "en"
i18n = Lang(DEFAULT_LANGUAGE)


def rank_label(rank):
    if rank is None:
        return "??k"

    if rank >= 0.5:
        return f"{rank:.0f}{i18n._('strength:dan')}"
    else:
        return f"{1-rank:.0f}{i18n._('strength:kyu')}"
