#!/usr/bin/env python
#
# Copyright (C) 2025 IOFactory
#
# Author: Luis Galdos <luis.galdos@iofactory.es>
#

from PyQt5.QtCore import Qt, QObject, QSettings, pyqtSignal
from PyQt5.QtGui import QColor

import functools


class Setting(QObject):

    signalUpdated = pyqtSignal()

    def __init__(self, parent, group, name, type_, default, widget):
        super().__init__()
        self.__parent = parent
        self.__group = group
        self.__name  = name
        self.__path  = self.__group.name() + "/" + self.__name
        self.__widgets = [ ]
        self.__type = type_
        self.__default = default
        self.__widget = widget

    def name(self):
        return self.__name

    def group(self):
        return self.__group

    @property
    def widget(self):
        return self.__widget

    @property
    def type(self):
        return self.__type

    def get(self):
        if self.__parent.contains(self.__path):
            return self.__parent.value(self.__path, type=self.__type)
        else:
            self.__parent.setValue(self.__path, self.__default)
            return self.__default

    def set(self, value):
        if type(value) != self.__type:
            print("Invalid type %s, expected %s" % (str(type(value)), str(self.__type)))
            return

        if self.get() != value:
            self.__parent.setValue(self.__path, value)
            self.signalUpdated.emit()


class Group(QObject):

    signalUpdated = pyqtSignal(Setting)

    def __init__(self, parent, name, params):
        QObject.__init__(self)
        self.__parent = parent
        self.__name = name

        self.__params = { }
        for p in params:
            param = Setting(parent, self, p[0], p[1], p[2], p[3])
            self.__params[p[0]] = param
            param.signalUpdated.connect(functools.partial(self.__slotUpdated, param))

    def name(self):
        return self.__name

    def __slotUpdated(self, param):
        self.signalUpdated.emit(param)

    def __getitem__(self, name):
        if name not in self.__params:
            raise IndexError("Unknown setting '%s' in group '%s'" % (name, self.__name))
        return self.__params[name]

    def __setitem__(self, name, value):
        self.__params[name].set(value)

    def __iter__(self):
        for each in self.__params.values():
            yield each

    def items(self):
        return self.__params.values()


class Settings(object):

    class __Settings(QSettings):
        def __init__(self):
            QSettings.__init__(self, "WarmiTEC", "KumiteApp")

            self.logging = Group(self, "logging",
                                 [
                                     ('path', str, "/tmp/kumite-app.log", 'LogPath'),
                                     ('level', str, 'INFO', 'LogLevel'),
                                     ('size', int, 1024 * 1024, 'LogSize'),
                                     ('backups', int, 2, 'LogBackups'),
                                 ])
            self.keys = Group(self, "keys",
                              [
                                  ('automatic', bool, False, 'KeysAutoCheck'),
                                  ('font_size', int, 12, 'KeysFontsizeSpinbox'),
                              ])
            self.colors_keys = Group(self, "colors_keys",
                                     [
                                         ('background', QColor, QColor(0, 0, 0), 'ColorKeysBackground'),
                                         ('frame_aka', QColor, QColor(0, 255, 0), 'ColorKeysFrameAka'),
                                         ('frame_ao', QColor, QColor(255, 0, 0), 'ColorKeysFrameAo'),
                                         ('lines', QColor, QColor(255, 255, 255), 'ColorKeysLines'),
                                         ('font', QColor, QColor(255, 255, 255), 'ColorKeysFont'),
                                     ])
            self.prompt = Group(self, "prompt",
                                [
                                    ('category', int, 70, 'PromptCategorySpinbox'),
                                    ('member', int, 40, 'PromptMemberSpinbox'),
                                    ('modality', int, 60, 'PromptModalitySpinbox'),
                                    ('penalty', int, 30, 'PromptPenaltySpinbox'),
                                    ('point', int, 120, 'PromptPointsSpinbox'),
                                    ('team', int, 180, 'PromptTeamsSpinbox'),
                                    ('time', int, 180, 'PromptTimeSpinbox'),
                                    ('tatami', int, 100, 'PromptTatamiSpinbox'),
                                    ('senshu', int, 20, 'PromptSenshuSpinbox'),
                                ])
            self.sounds = Group(self, "sounds",
                                [
                                    ('time_1', list, [0, ''], None),
                                    ('time_2', list, [0, ''], None),
                                    ('time_3', list, [0, ''], None),
                                ])
            self.panel = Group(self, "panel",
                                [
                                    ('ao', QColor, QColor(0, 0, 255), 'ColorPanelAo'),
                                    ('ao_off', QColor, QColor(80, 80, 170), 'ColorPanelAoOff'),
                                    ('aka', QColor, QColor(255, 0, 0), 'ColorPanelAka'),
                                    ('aka_off', QColor, QColor(170, 80, 80), 'ColorPanelAkaOff'),
                                    ('start_button', QColor, QColor(10, 180, 80), 'ColorStartButton'),
                                ])

        def groups(self):
            # IMPORTANT dont add sounds as handled in different manner
            return [self.logging, self.keys, self.colors_keys, self.prompt, self.panel]

        def save(self):
            super().sync()

        def get_widgets(self, parent, widget_type):
            found = []
            for group in self.groups():
                for item in group.items():
                    if item.type == widget_type:
                        w = getattr(parent, item.widget)
                        found.append((item, w))
            return found


    _instance = None

    def __new__(cls):
        if not Settings._instance:
            Settings._instance = Settings.__Settings()
        return Settings._instance

    def __getattr__(self, name):
        return getattr(self._instance, name)

    def __setattr__(self, name):
        return setattr(self._instance, name)
