from pathlib import Path
import copy
import importlib.util
import json
import shutil
import sys
import tkinter as tk
from tkinter import ttk


APP = Path(__file__).resolve().parent
V39_PATH = APP / "racecore_studio_v39.py"
if str(APP) not in sys.path:
    sys.path.insert(0, str(APP))

spec = importlib.util.spec_from_file_location("racecore_v39_for_v40", V39_PATH)
v39 = importlib.util.module_from_spec(spec)
spec.loader.exec_module(v39)

from core.focus_canvas import FocusCanvasRenderer
from core.panel_painter import PanelHitTester
import core.panel_painter as panel_painter_module
from core.paths import StudioPaths
from core.render_pipeline import RenderPipeline
from core.vehicle_profiles import (
    DEFAULT_VEHICLE_ID,
    VEHICLE_CATEGORY_ORDER,
    load_vehicle_profiles,
)


V35 = v39.v38.v37.v36.v35
V34 = V35.v34
V33 = V34.v33
V32 = V33.v32
V31 = V32.v31
V30 = V31.v30
V29 = V30.v29
V28 = V29.v28
V27 = V28.v27
V26 = V27.v26
V25 = V26.v25
V24 = V25.v24
V23 = V24.v23
V22 = V23.v22

FERRARI_GUIDES_X = tuple(V29.FERRARI_GUIDES_X)
FERRARI_GUIDES_Y = tuple(V29.FERRARI_GUIDES_Y)


class StudioV40(v39.StudioV39):
    """LMU-voertuigen met een volledig gescheiden profiel per model."""

    def __init__(self):
        self.vehicle_catalog = load_vehicle_profiles(APP)
        self.vehicle_id = DEFAULT_VEHICLE_ID
        self.vehicle_switching = False
        self.vehicle_label_to_id = {
            profile.label: profile.vehicle_id
            for profile in self.vehicle_catalog.values()
        }
        self.vehicle_var = None
        categories = {profile.category for profile in self.vehicle_catalog.values()}
        self.vehicle_categories = tuple(
            category for category in VEHICLE_CATEGORY_ORDER if category in categories
        ) + tuple(sorted(categories.difference(VEHICLE_CATEGORY_ORDER)))
        self.vehicle_category_var = None
        self.vehicle_category_combo = None
        super().__init__()

        legacy = StudioPaths(APP, DEFAULT_VEHICLE_ID).autosave
        target = self.vehicle_autosave_path(DEFAULT_VEHICLE_ID)
        if legacy.exists() and not target.exists():
            target.parent.mkdir(parents=True, exist_ok=True)
            shutil.copy2(legacy, target)

        self._activate_vehicle_profile(self.vehicle_id, refresh=False)
        self.title("RaceCore Livery Studio v4.0 - Multi GT3")
        self.generate(False)

    def build_layout(self):
        super().build_layout()
        header = self.winfo_children()[0]
        for child in tuple(header.winfo_children()):
            if not isinstance(child, tk.Label):
                continue
            text = str(child.cget("text"))
            if "Livery Studio" in text:
                child.configure(text="Livery Studio  v4.0")
            elif "Ferrari 296" in text:
                child.destroy()

        profile = self.vehicle_catalog[self.vehicle_id]
        self.vehicle_var = tk.StringVar(master=self, value=profile.label)
        self.vehicle_category_var = tk.StringVar(
            master=self, value=profile.category
        )
        style = ttk.Style(self)
        style.configure(
            "RaceCore.Vehicle.TCombobox",
            fieldbackground="#17233A", background="#17233A",
            foreground="#F8FAFC", arrowcolor="#67E8F9",
        )
        combo = ttk.Combobox(
            header, textvariable=self.vehicle_var,
            values=[item.label for item in self.vehicle_catalog.values()],
            state="readonly", width=31, font=("Segoe UI", 10, "bold"),
            style="RaceCore.Vehicle.TCombobox",
        )
        combo.pack(side="right", padx=(8, 28), pady=18)
        combo.bind("<<ComboboxSelected>>", self.vehicle_selected)
        self.vehicle_combo = combo
        tk.Label(
            header, text="AUTO", font=("Segoe UI", 8, "bold"),
            fg="#67E8F9", bg="#08152C",
        ).pack(side="right", padx=(0, 0), pady=18)

        if getattr(self, "carrosserie_menu", None):
            try:
                self.carrosserie_menu[1].entryconfigure(
                    0, label="Originele voertuigtemplate opnieuw laden"
                )
            except tk.TclError:
                pass

    @property
    def active_vehicle(self):
        return self.vehicle_catalog[self.vehicle_id]

    def vehicles_for_category(self, category=None):
        active_category = category or self.active_vehicle.category
        return tuple(
            profile for profile in self.vehicle_catalog.values()
            if profile.category == active_category
        )

    def _sync_vehicle_filter(self):
        if self.vehicle_category_var is not None:
            self.vehicle_category_var.set(self.active_vehicle.category)
        combo = getattr(self, "vehicle_combo", None)
        if combo is not None:
            combo.configure(
                values=[
                    profile.label
                    for profile in self.vehicles_for_category(
                        self.active_vehicle.category
                    )
                ]
            )
        if self.vehicle_var is not None:
            self.vehicle_var.set(self.active_vehicle.label)

    def vehicle_category_selected(self, _event=None):
        if self.vehicle_switching or self.vehicle_category_var is None:
            return
        category = self.vehicle_category_var.get()
        candidates = self.vehicles_for_category(category)
        if not candidates:
            self._sync_vehicle_filter()
            return
        if self.active_vehicle.category == category:
            self._sync_vehicle_filter()
            return
        if getattr(self, "vehicle_combo", None) is not None:
            self.vehicle_combo.configure(
                values=[profile.label for profile in candidates]
            )
        self.vehicle_var.set(candidates[0].label)
        self.vehicle_selected()

    def vehicle_autosave_path(self, vehicle_id=None):
        active = vehicle_id or self.vehicle_id
        return StudioPaths(APP, active).autosaves / f"{active}.racecore.json"

    def autosave(self):
        path = self.vehicle_autosave_path()
        path.parent.mkdir(parents=True, exist_ok=True)
        staging = path.with_name(path.name + ".racecore-staging")
        staging.write_text(
            json.dumps(self.snapshot(), indent=2), encoding="utf-8"
        )
        staging.replace(path)

    def snapshot(self):
        state = super().snapshot()
        state["schemaVersion"] = max(10, int(state.get("schemaVersion", 0)))
        state["vehicleId"] = self.vehicle_id
        state["vehicleLabel"] = self.active_vehicle.label
        return state

    def apply_state(self, state, record=False):
        state = copy.deepcopy(state)
        requested = str(state.get("vehicleId", self.vehicle_id))
        if requested in self.vehicle_catalog and requested != self.vehicle_id:
            self._activate_vehicle_profile(requested, refresh=False)
        super().apply_state(state, record)
        if self.vehicle_var is not None:
            self._sync_vehicle_filter()

    def _set_panel_profile(self, profile):
        panels = tuple(profile.panels)
        labels = dict(panels)
        panel_painter_module.PANELS = panels
        panel_painter_module.PANEL_LABELS.clear()
        panel_painter_module.PANEL_LABELS.update(labels)
        V22.PANELS = panels
        V23.PANELS = panels
        for mapping in (V22.PANEL_LABELS, V23.PANEL_LABELS, V35.PANEL_LABELS):
            mapping.clear()
            mapping.update(labels)
        if profile.vehicle_id == DEFAULT_VEHICLE_ID:
            V29.FERRARI_GUIDES_X = FERRARI_GUIDES_X
            V29.FERRARI_GUIDES_Y = FERRARI_GUIDES_Y
        else:
            V29.FERRARI_GUIDES_X = ()
            V29.FERRARI_GUIDES_Y = ()

    def _activate_vehicle_profile(self, vehicle_id, refresh=True):
        profile = self.vehicle_catalog[vehicle_id]
        self.vehicle_id = vehicle_id
        self._set_panel_profile(profile)
        with self._render_lock:
            self._render_request += 1
            self.pipeline = RenderPipeline(StudioPaths(APP, vehicle_id))
            self.pipeline.source.verify()
            self.focus_renderer = FocusCanvasRenderer(self.pipeline)
            self.focus_master = None
            self.focus_cache = None
            self.panel_hit_tester = PanelHitTester(
                self.pipeline.masks, panels=profile.panels
            )
            self.brush_live_surface = None
            self.brush_live_metrics = None
            self.focus_viewport.fit()
        if self.vehicle_var is not None:
            self._sync_vehicle_filter()
        if refresh:
            self.generate(False)

    def vehicle_selected(self, _event=None):
        if self.vehicle_switching or self.vehicle_var is None:
            return
        target = self.vehicle_label_to_id.get(self.vehicle_var.get())
        if not target or target == self.vehicle_id:
            return
        self.vehicle_switching = True
        try:
            self.autosave()
            if self.panel_paint_mode:
                self.cancel_panel_paint(refresh=False)
            self._activate_vehicle_profile(target, refresh=False)
            saved = self.vehicle_autosave_path(target)
            if saved.exists():
                self.load_path(saved, record=False)
            else:
                self.new_blank_project()
            self.focus_viewport.fit()
            self.focus_master = None
            self.focus_cache = None
            self.refresh_layer_sidebar()
            self.status.set(
                f"{self.active_vehicle.label} geladen | eigen LMU-template actief"
            )
            self.generate(False)
        finally:
            self.vehicle_switching = False

    def restore_original_template(self):
        super().restore_original_template()
        self.status.set(
            f"Originele {self.active_vehicle.label}-template opnieuw geladen"
        )


if __name__ == "__main__":
    StudioV40().mainloop()
