from pathlib import Path
from typing import Dict, List, TYPE_CHECKING, Optional, cast

import axipy as axp
from .model import StyleKey, StyleSet
from .utils import StrEnumMeta

if TYPE_CHECKING:
    from .__init__ import StyleCatalogs


class SettingKey(StrEnumMeta):
    # back compat
    KEYS_ORDER_LIST = "keys_order_list"
    ITEMS_DICT = "items_dict"

    STYLE_SETS = "style_sets"


class SettingsManager:

    def __init__(self, plugin: 'StyleCatalogs') -> None:
        self.plugin = plugin
        self.settings = self.plugin.settings

    def get_style_sets(self) -> List['StyleSet']:
        style_sets: Optional[List['StyleSet']] = self.settings.value(SettingKey.STYLE_SETS, None)

        # try back compat
        if style_sets is None:
            # if style sets is not None, it already means, that old settings were already checked.

            style_keys = {
                "brush": StyleKey.BRUSH,
                "pen": StyleKey.PEN,
                "symbol": StyleKey.SYMBOL,
            }
            style_sets: List['StyleSet'] = []
            items_dict: Dict[str, Dict[str, str]] = self.settings.value(SettingKey.ITEMS_DICT, None)
            keys_order_list: List[str] = self.settings.value(SettingKey.KEYS_ORDER_LIST, None)

            if items_dict is None or keys_order_list is None:
                return []

            items_dict_formatted: Dict[str, Dict[StyleKey, Path]] = {}
            for k, v in items_dict.items():
                inner_dict_formatted: Dict[StyleKey, Path] = {}
                for k2, v2 in v.items():
                    inner_dict_formatted[style_keys[k2]] = Path(v2)
                items_dict_formatted[k] = inner_dict_formatted

            for key in keys_order_list:
                style_set = StyleSet(key, items_dict_formatted[key])
                style_sets.append(style_set)

        if style_sets is None:
            return []
        else:
            return self.ensure_style_sets(style_sets)

    @staticmethod
    def ensure_style_sets(style_sets: List['StyleSet']) -> List['StyleSet']:
        new_style_sets = []
        for style_set in style_sets:
            new_style_set = StyleSet(style_set.name, style_set.items, style_set.is_active)
            new_style_sets.append(new_style_set)
        return new_style_sets

    def save_style_sets(self, style_sets: List['StyleSet']) -> None:
        self.settings.setValue(SettingKey.STYLE_SETS, style_sets)

    def apply_style_catalogs_settings(self) -> None:
        active_style_set = None
        style_sets = self.get_style_sets()
        for style_set in style_sets:
            if style_set.is_active:
                active_style_set = style_set

        if active_style_set is None:
            self.apply_defaults()
            return None

        try:
            axp.CurrentSettings.PenCatalog = active_style_set.items[StyleKey.PEN]
            axp.CurrentSettings.BrushCatalog = active_style_set.items[StyleKey.BRUSH]
            axp.CurrentSettings.SymbolCatalog = active_style_set.items[StyleKey.SYMBOL]
        except (Exception,):
            self.apply_defaults()

    @staticmethod
    def apply_defaults() -> None:
        if axp.CurrentSettings.PenCatalog != axp.DefaultSettings.PenCatalog:
            axp.CurrentSettings.PenCatalog = axp.DefaultSettings.PenCatalog
        if axp.CurrentSettings.BrushCatalog != axp.DefaultSettings.BrushCatalog:
            axp.CurrentSettings.BrushCatalog = axp.DefaultSettings.BrushCatalog
        if axp.CurrentSettings.SymbolCatalog != axp.DefaultSettings.SymbolCatalog:
            axp.CurrentSettings.SymbolCatalog = axp.DefaultSettings.SymbolCatalog
