from __future__ import annotations

import tkinter as tk
from importlib import import_module, resources
from pathlib import Path
from tkinter import ttk


class IconStore:
    """Load and cache Material Design icons used by ttk widgets."""

    def __init__(self, master: tk.Misc):
        self.master = master
        self.style = ttk.Style(master)
        self._cache: dict[tuple[str, int, str], tk.PhotoImage | None] = {}
        self._mat_icon = self._load_mat_icon_class()

    def get(self, name: str, size: int = 16, color: str | None = None) -> tk.PhotoImage | None:
        resolved_color = color or self._theme_color()
        key = (name, size, resolved_color)
        if key not in self._cache:
            self._cache[key] = self._load(name, size, resolved_color)
        return self._cache[key]

    def clear(self) -> None:
        self._cache.clear()

    def _load(self, name: str, size: int, color: str) -> tk.PhotoImage | None:
        if self._mat_icon:
            try:
                return self._mat_icon(name, size=size, color=color).image
            except Exception:
                pass
        return self._load_asset_fallback(name, size)

    def _load_asset_fallback(self, name: str, size: int) -> tk.PhotoImage | None:
        for module_name in ("ttkbootstrap_icons_mat", "ttkbootstrap_icons"):
            try:
                root = resources.files(import_module(module_name))
            except (ImportError, TypeError):
                continue
            candidates = {name, name.replace("-", "_"), name.replace("_", "-")}
            for candidate in candidates:
                for extension in (".png", ".gif"):
                    try:
                        path = Path(next(root.rglob(f"{candidate}{extension}")))
                        image = tk.PhotoImage(master=self.master, file=str(path))
                        if size and image.width() > size:
                            factor = max(1, round(image.width() / size))
                            image = image.subsample(factor, factor)
                        return image
                    except (StopIteration, tk.TclError, OSError):
                        continue
        return None

    @staticmethod
    def _load_mat_icon_class():
        try:
            module = import_module("ttkbootstrap_icons_mat")
        except ImportError:
            return None
        return getattr(module, "MatIcon", None)

    def _theme_color(self) -> str:
        try:
            theme_name = self.style.theme_use().lower()
        except tk.TclError:
            theme_name = ""
        if "dark" in theme_name:
            return "#eeeeee"
        if "light" in theme_name:
            return "#313131"
        background = self.style.lookup("TFrame", "background") or "#ffffff"
        try:
            red, green, blue = self.master.winfo_rgb(background)
            luminance = (0.2126 * red + 0.7152 * green + 0.0722 * blue) / 65535
            return "#eeeeee" if luminance < 0.5 else "#313131"
        except tk.TclError:
            return "#313131"
