"""Vorschaubilder der Materialbibliothek (icons/) und Hintergrund-Rendering.

Jedes Material bekommt ein 256er-PNG in ``icons/``, gerendert mit der
mitgelieferten ``preview_scene.blend``. Beim Hinzufuegen oder Aktualisieren
eines Materials rendert ein Blender-Hintergrundprozess (``render_preview.py``)
das Bild automatisch neu; ein Timer laedt es danach in die UI.
"""

import os
import re
import subprocess

import bpy
import bpy.utils.previews

from .material import material_manager

_cache = None        # bpy.utils.previews-Sammlung (lazy)
_enum_items = []     # WICHTIG: haelt die Enum-Strings am Leben (Blender-Falle)
_kategorie_items = []


def _addon_dir():
    return os.path.dirname(os.path.realpath(__file__))


def sicherer_name(name):
    return re.sub(r"[^A-Za-z0-9_-]", "_", name)


def icon_id(name):
    global _cache
    if _cache is None:
        _cache = bpy.utils.previews.new()
    key = sicherer_name(name)
    if key not in _cache:
        pfad = os.path.join(_addon_dir(), "icons", key + ".png")
        if not os.path.exists(pfad):
            return 0
        _cache.load(key, pfad, 'IMAGE')
    return _cache[key].icon_id


def leere_cache():
    global _cache
    if _cache is not None:
        bpy.utils.previews.remove(_cache)
        _cache = None


def material_enum_items(self, context):
    global _enum_items
    kategorie = None
    if context is not None:
        kategorie = getattr(context.scene, "material_category", None)
    treffer = [m for m in material_manager.material_data
               if not kategorie or m.category == kategorie]
    items = [(m.name, m.name, m.category, icon_id(m.name), i)
             for i, m in enumerate(treffer)]
    if not items:
        items = [("NONE", "-", "Keine Materialien in dieser Kategorie", 0, 0)]
    _enum_items = items
    return items


def kategorie_enum_items(self, context):
    global _kategorie_items
    kategorien = sorted(set(m.category for m in material_manager.material_data))
    _kategorie_items = [(k, k, '') for k in kategorien] or [("NONE", "-", '')]
    return _kategorie_items


def starte_render(material_name):
    """Rendert das Vorschaubild eines Materials im Hintergrund neu."""
    addon_dir = _addon_dir()
    szene = os.path.join(addon_dir, "preview_scene.blend")
    skript = os.path.join(addon_dir, "render_preview.py")
    if not (os.path.exists(szene) and os.path.exists(skript)):
        print("BaseMaterials: preview_scene.blend/render_preview.py fehlt - kein Auto-Preview.")
        return
    icons_dir = os.path.join(addon_dir, "icons")
    pfad = os.path.join(icons_dir, sicherer_name(material_name) + ".png")
    vorher = os.path.getmtime(pfad) if os.path.exists(pfad) else None
    try:
        subprocess.Popen(
            [bpy.app.binary_path, "--background", szene, "--factory-startup",
             "--python", skript, "--", addon_dir, icons_dir, material_name],
            stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
    except Exception as fehler:
        print(f"BaseMaterials: Preview-Render nicht gestartet: {fehler}")
        return

    versuche = [0]

    def _warte_auf_bild():
        versuche[0] += 1
        if versuche[0] > 90:            # nach ~3 Minuten aufgeben
            return None
        try:
            fertig = os.path.exists(pfad) and os.path.getmtime(pfad) != vorher
        except OSError:
            fertig = False
        if not fertig:
            return 2.0                  # in 2 s nochmal nachsehen
        leere_cache()                   # Icon beim naechsten Zeichnen neu laden
        try:
            for fenster in bpy.context.window_manager.windows:
                for bereich in fenster.screen.areas:
                    bereich.tag_redraw()
        except Exception:
            pass
        return None

    bpy.app.timers.register(_warte_auf_bild, first_interval=2.0)
