from pathlib import Path
import importlib.util
import math
import sys
import tkinter as tk

from PIL import ImageDraw, ImageTk


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

spec = importlib.util.spec_from_file_location("racecore_v35_for_v36", V35_PATH)
v35 = importlib.util.module_from_spec(spec)
spec.loader.exec_module(v35)

from core.panel_painter import brush_layer


class StudioV36(v35.StudioV35):
    """Vrij schilderen met de muis, opgeslagen als losse creatieve laag."""

    def __init__(self):
        self.brush_strokes = []
        self.brush_dragging = False
        super().__init__()
        self.title("RaceCore Livery Studio v3.6 - Vrij Schilderen")

    def build_layout(self):
        super().build_layout()
        header = self.winfo_children()[0]
        for child in header.winfo_children():
            if isinstance(child, tk.Label) and "Livery Studio" in child.cget("text"):
                child.configure(text="Livery Studio  v3.6")

        # De paneelknoppen hebben nog één vrije positie in hun rustige 2x2-grid.
        for child in self.design_toolbox.winfo_children():
            buttons = [item for item in child.winfo_children() if isinstance(item, tk.Button)]
            if any(item.cget("text") == "PANEEL AANKLIKKEN" for item in buttons):
                tk.Button(
                    child, text="VRIJ SCHILDEREN", command=self.start_brush_paint,
                    font=("Segoe UI", 8, "bold"), fg="#F8FAFC", bg="#0F766E",
                    activeforeground="#FFFFFF", activebackground="#475569",
                    relief="flat", padx=5, pady=7, anchor="w",
                ).grid(row=1, column=1, sticky="ew", padx=2, pady=2)
                break

        viewer = self.preview_label.master
        controls = tk.Frame(viewer, bg="#11151D", bd=1, relief="solid")
        controls.place(relx=.5, y=16, anchor="n")
        controls.place_forget()
        self.brush_controls = controls
        self.brush_status = tk.StringVar(master=self, value="")
        self.brush_size = tk.IntVar(master=self, value=90)

        tk.Label(
            controls, textvariable=self.brush_status,
            font=("Segoe UI", 9, "bold"), fg="#F8FAFC", bg="#11151D",
            padx=9,
        ).pack(side="left", pady=6)
        tk.Label(
            controls, text="DIKTE", font=("Segoe UI", 8, "bold"),
            fg="#94A3B8", bg="#11151D",
        ).pack(side="left", padx=(2, 0))
        tk.Scale(
            controls, from_=10, to=320, orient="horizontal", showvalue=False,
            variable=self.brush_size, command=self.brush_size_changed,
            bg="#11151D", troughcolor="#334155", activebackground="#22D3EE",
            highlightthickness=0, bd=0, sliderrelief="flat", length=120,
        ).pack(side="left", padx=4)
        self.brush_size_label = tk.Label(
            controls, text="90 px", width=6, font=("Segoe UI", 8, "bold"),
            fg="#67E8F9", bg="#11151D",
        )
        self.brush_size_label.pack(side="left", padx=(0, 5))
        self.brush_undo_button = self._brush_button(
            controls, "STREEK TERUG", self.undo_brush_stroke, "#334155"
        )
        self.brush_finish_button = self._brush_button(
            controls, "OPSLAAN", self.finish_brush_paint, "#0F766E"
        )
        self._brush_button(
            controls, "ANNULEREN", self.cancel_panel_paint, "#7F1D1D"
        )

        self.preview_label.bind("<ButtonPress-1>", self.preview_press)
        self.preview_label.bind("<B1-Motion>", self.preview_drag)
        self.preview_label.bind("<ButtonRelease-1>", self.preview_release)

    @staticmethod
    def _brush_button(parent, text, command, colour):
        button = tk.Button(
            parent, text=text, command=command, font=("Segoe UI", 8, "bold"),
            fg="#F8FAFC", bg=colour, activeforeground="#FFFFFF",
            activebackground="#475569", relief="flat", padx=8, pady=5,
        )
        button.pack(side="left", padx=(0, 4), pady=4)
        return button

    def start_brush_paint(self):
        self.panel_paint_mode = "brush"
        self.brush_strokes = []
        self.brush_dragging = False
        self.hide_design_toolbox()
        self.focus_mode.set("design")
        self.focus_show_uv.set(True)
        self._refresh_mode_buttons()
        self.sticker_toggle.configure(state="normal")
        self.brush_controls.place(relx=.5, y=16, anchor="n")
        self.brush_controls.lift()
        self.preview_label.configure(cursor="crosshair")
        self.preview_label.focus_set()
        self._update_brush_controls()
        self.show_selection_overlay()
        self.status.set(
            "Vrij schilderen | houd de linkermuisknop ingedrukt en kleur over het paneel"
        )

    def brush_size_changed(self, raw=None):
        if raw is not None:
            self.brush_size.set(int(round(float(raw))))
        if hasattr(self, "brush_size_label"):
            self.brush_size_label.configure(text=f"{self.brush_size.get()} px")
        if self.panel_paint_mode == "brush":
            self.show_selection_overlay()

    def _update_brush_controls(self):
        count = len(self.brush_strokes)
        self.brush_status.set(
            f"VRIJ SCHILDEREN  •  {count} {'STREEK' if count == 1 else 'STREKEN'}"
        )
        self.brush_undo_button.configure(state="normal" if count else "disabled")
        self.brush_finish_button.configure(state="normal" if count else "disabled")
        self.brush_size_label.configure(text=f"{self.brush_size.get()} px")

    def preview_press(self, event):
        if self.panel_paint_mode != "brush":
            return super().preview_press(event)
        point = self.event_to_texture(event)
        if point is None:
            return "break"
        self.brush_strokes.append([self._clean_brush_point(point)])
        self.brush_dragging = True
        self._update_brush_controls()
        self.show_selection_overlay()
        return "break"

    def preview_drag(self, event):
        if self.panel_paint_mode != "brush":
            return super().preview_drag(event)
        if not self.brush_dragging or not self.brush_strokes:
            return "break"
        point = self.event_to_texture(event)
        if point is None:
            return "break"
        point = self._clean_brush_point(point)
        previous = self.brush_strokes[-1][-1]
        if math.hypot(point[0] - previous[0], point[1] - previous[1]) >= 2:
            self.brush_strokes[-1].append(point)
            self.show_selection_overlay()
        return "break"

    def preview_release(self, event):
        if self.panel_paint_mode != "brush":
            return super().preview_release(event)
        self.brush_dragging = False
        self._update_brush_controls()
        self.status.set(
            f"{len(self.brush_strokes)} streken | schilder verder of kies OPSLAAN"
        )
        return "break"

    @staticmethod
    def _clean_brush_point(point):
        return (
            max(0.0, min(4096.0, float(point[0]))),
            max(0.0, min(4096.0, float(point[1]))),
        )

    def undo_brush_stroke(self):
        if self.panel_paint_mode != "brush" or not self.brush_strokes:
            return
        self.brush_strokes.pop()
        self.brush_dragging = False
        self._update_brush_controls()
        self.show_selection_overlay()

    def finish_brush_paint(self):
        if self.panel_paint_mode != "brush":
            return
        if not self.brush_strokes:
            self.status.set("Schilder eerst minimaal één streek")
            return
        layer = self.normalise_shape(brush_layer(
            self.brush_strokes, self.brush_size.get(), self.accent.get(),
            len(self.shape_layers) + 1,
        ))
        self.shape_layers.append(layer)
        self.panel_paint_mode = None
        self.brush_strokes = []
        self.brush_dragging = False
        self.brush_controls.place_forget()
        self.preview_label.configure(cursor="crosshair")
        self._finish_quick_add(
            "shape", layer,
            "Penseelwerk opgeslagen als losse laag"
        )

    def cancel_panel_paint(self, refresh=True):
        brush_was_active = self.panel_paint_mode == "brush"
        self.brush_strokes = []
        self.brush_dragging = False
        if hasattr(self, "brush_controls"):
            self.brush_controls.place_forget()
        super().cancel_panel_paint(refresh=refresh)
        if brush_was_active and refresh:
            self.status.set("Vrij schilderen geannuleerd")

    def show_selection_overlay(self):
        if self.panel_paint_mode != "brush":
            super().show_selection_overlay()
            self._lift_brush_tools()
            return
        if self.focus_master is None or not hasattr(self, "preview_label"):
            return
        try:
            width = max(1, self.preview_label.winfo_width())
            height = max(1, self.preview_label.winfo_height())
            image, metrics = self.focus_viewport.render(self.focus_master, width, height)
            draw = ImageDraw.Draw(image)
            left, _top, right, _bottom = metrics.crop
            display_size = max(2, round(
                self.brush_size.get() * metrics.size / max(1, right - left)
            ))
            radius = display_size / 2
            colour = self.accent.get().upper()
            for stroke in self.brush_strokes:
                points = [self._texture_point(point, metrics.size) for point in stroke]
                if len(points) >= 2:
                    draw.line(
                        points, fill=colour, width=display_size, joint="curve"
                    )
                for x, y in (points if len(points) == 1 else (points[0], points[-1])):
                    draw.ellipse(
                        (x - radius, y - radius, x + radius, y + radius),
                        fill=colour,
                    )
            self._publish_preview_image(image)
            self.focus_tools.lift()
            self._lift_brush_tools()
        except (OSError, ValueError, tk.TclError):
            pass

    def _lift_brush_tools(self):
        if hasattr(self, "brush_controls") and self.brush_controls.winfo_ismapped():
            self.brush_controls.lift()


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