from pathlib import Path
from PIL import Image, ImageTk, ImageDraw, ImageEnhance, ImageChops
import colorsys, json, subprocess, sys, threading, tkinter as tk
from tkinter import colorchooser, messagebox

ROOT = Path(__file__).resolve().parents[2]
APP = Path(__file__).resolve().parent
SOURCE = ROOT / "outputs" / "Ferrari_296_Colour_Proof" / "backup_before_install_2026-08-03" / "customskin.tga"
MASKS = ROOT / "outputs" / "Car_Profile_v0.3" / "masks"
SEAM_PROJECT = ROOT / "outputs" / "Seam_Aware_v0.5" / "ferrari_seam_proof.racecore.json"
GENERATED = APP / "generated"
LIVE_LINK = ROOT / "outputs" / "Live_Link_v0.6" / "live_link.py"
LIVE_CONFIG = APP / "live-link-ui.json"

NAVY = "#07152f"; PANEL = "#101f3c"; BLUE = "#2563eb"; CYAN = "#22d3ee"; TEXT = "#f8fafc"; MUTED = "#94a3b8"


def rgb(hex_value):
    value=hex_value.lstrip('#'); return tuple(int(value[i:i+2],16) for i in (0,2,4))


def load_l(name): return Image.open(MASKS/name).convert('L')


class Studio(tk.Tk):
    def __init__(self):
        super().__init__()
        self.title("RaceCore Livery Studio - Ferrari 296")
        self.geometry("1280x820"); self.minsize(1080,720); self.configure(bg=NAVY)
        self.primary=tk.StringVar(value="#05122D"); self.accent=tk.StringVar(value="#00E5FF")
        self.width=tk.IntVar(value=100); self.status=tk.StringVar(value="Klaar voor ontwerp")
        self.preview_photo=None
        self.build_layout(); self.after(150,lambda:self.generate(False))

    def build_layout(self):
        header=tk.Frame(self,bg=NAVY,height=72); header.pack(fill='x'); header.pack_propagate(False)
        tk.Label(header,text="RACECORE",font=("Segoe UI",20,"bold"),fg=CYAN,bg=NAVY).pack(side='left',padx=(28,12))
        tk.Label(header,text="Livery Studio  v0.7",font=("Segoe UI",16),fg=TEXT,bg=NAVY).pack(side='left')
        tk.Label(header,text="Ferrari 296 LMGT3 EVO",font=("Segoe UI",11),fg=MUTED,bg=NAVY).pack(side='right',padx=28)

        body=tk.Frame(self,bg=NAVY); body.pack(fill='both',expand=True,padx=20,pady=(0,14))
        controls=tk.Frame(body,bg=PANEL,width=300); controls.pack(side='left',fill='y',padx=(0,14)); controls.pack_propagate(False)
        viewer=tk.Frame(body,bg="#050b18"); viewer.pack(side='left',fill='both',expand=True)
        self.preview_label=tk.Label(viewer,text="Preview wordt opgebouwd...",font=("Segoe UI",12),fg=MUTED,bg="#050b18")
        self.preview_label.pack(fill='both',expand=True,padx=12,pady=12)

        self.section(controls,"LAK")
        self.colour_row(controls,"Basiskleur",self.primary)
        self.colour_row(controls,"Accentkleur",self.accent)
        self.section(controls,"VECTOR STRIPES")
        tk.Label(controls,text="Lijnbreedte",font=("Segoe UI",10),fg=TEXT,bg=PANEL).pack(anchor='w',padx=20,pady=(4,0))
        tk.Scale(controls,from_=50,to=170,orient='horizontal',variable=self.width,command=lambda _=None:self.schedule_preview(),
                 bg=PANEL,fg=TEXT,troughcolor="#253656",highlightthickness=0,activebackground=CYAN).pack(fill='x',padx=16)
        tk.Label(controls,text="Semantische bescherming",font=("Segoe UI",10,"bold"),fg=TEXT,bg=PANEL).pack(anchor='w',padx=20,pady=(18,5))
        for item in ["✓ Nummerplaten","✓ Class stickers","✓ Car stickers","✓ Displaypanelen"]:
            tk.Label(controls,text=item,font=("Segoe UI",10),fg="#86efac",bg=PANEL).pack(anchor='w',padx=22,pady=2)
        tk.Frame(controls,bg=PANEL).pack(fill='both',expand=True)
        tk.Button(controls,text="PREVIEW",command=lambda:self.generate(False),font=("Segoe UI",11,"bold"),fg=TEXT,bg="#334155",activebackground="#475569",relief='flat',pady=11).pack(fill='x',padx=18,pady=(8,8))
        tk.Button(controls,text="APPLY TO LMU",command=lambda:self.generate(True),font=("Segoe UI",11,"bold"),fg=NAVY,bg=CYAN,activebackground="#67e8f9",relief='flat',pady=13).pack(fill='x',padx=18,pady=(0,20))

        footer=tk.Frame(self,bg="#0b1730",height=44); footer.pack(fill='x'); footer.pack_propagate(False)
        tk.Label(footer,textvariable=self.status,font=("Segoe UI",10),fg=MUTED,bg="#0b1730").pack(side='left',padx=22)
        tk.Label(footer,text="LIVE LINK  ●",font=("Segoe UI",10,"bold"),fg="#4ade80",bg="#0b1730").pack(side='right',padx=22)

    def section(self,parent,text):
        tk.Label(parent,text=text,font=("Segoe UI",9,"bold"),fg=CYAN,bg=PANEL).pack(anchor='w',padx=20,pady=(20,10))

    def colour_row(self,parent,label,var):
        row=tk.Frame(parent,bg=PANEL); row.pack(fill='x',padx=20,pady=6)
        tk.Label(row,text=label,font=("Segoe UI",10),fg=TEXT,bg=PANEL).pack(side='left')
        swatch=tk.Button(row,textvariable=var,font=("Consolas",9),width=10,fg=TEXT,bg="#263858",relief='flat',
                         command=lambda:self.pick_colour(var)); swatch.pack(side='right')

    def pick_colour(self,var):
        picked=colorchooser.askcolor(var.get(),title="Kies RaceCore-kleur")[1]
        if picked: var.set(picked.upper()); self.schedule_preview()

    def schedule_preview(self):
        if hasattr(self,'preview_job'): self.after_cancel(self.preview_job)
        self.preview_job=self.after(350,lambda:self.generate(False))

    def generate(self,apply):
        self.status.set("Texture wordt opgebouwd..."); self.update_idletasks()
        threading.Thread(target=self._worker,args=(apply,),daemon=True).start()

    def _worker(self,apply):
        try:
            GENERATED.mkdir(parents=True,exist_ok=True)
            cfg=json.loads(SEAM_PROJECT.read_text(encoding='utf-8'))
            source=Image.open(SOURCE).convert('RGB'); size=source.size
            body=load_l('carbon.png'); protected=Image.new('L',size,0)
            for name in ['number_plates.png','class_stickers.png','car_stickers.png','display_panels.png']:
                protected=ImageChops.lighter(protected,load_l(name))
            editable=ImageChops.subtract(body,protected)
            gray=source.convert('L'); shade=Image.merge('RGB',(gray,gray,gray))
            primary=Image.new('RGB',size,rgb(self.primary.get()))
            canvas=Image.composite(ImageEnhance.Brightness(ImageChops.multiply(primary,shade)).enhance(2.15),source,editable)
            line_mask=Image.new('L',size,0)
            scale=self.width.get()/100.0
            for graph in cfg['seamGraph']:
                for segment in graph['segments']:
                    ImageDraw.Draw(line_mask).line([tuple(p) for p in segment['points']],fill=255,width=max(2,round(segment['width']*scale)),joint='curve')
            line_mask=ImageChops.multiply(line_mask,editable)
            canvas=Image.composite(Image.new('RGB',size,rgb(self.accent.get())),canvas,line_mask)
            canvas=Image.composite(source,canvas,protected)
            canvas.save(GENERATED/'customskin.tga',format='TGA',compression=None)
            Image.new('RGB',size,(0,0,0)).save(GENERATED/'customskin_region.tga',format='TGA',compression=None)
            preview=canvas.copy(); preview.thumbnail((880,680)); preview.save(GENERATED/'preview.png',optimize=True)
            if apply:
                result=subprocess.run([sys.executable,str(LIVE_LINK),str(LIVE_CONFIG)],capture_output=True,text=True,timeout=60)
                if result.returncode: raise RuntimeError(result.stderr.strip() or result.stdout.strip())
                event=json.loads(result.stdout); label="Live in LMU" if event['status']=='installed' else "LMU is al bijgewerkt"
            else: label="Preview gereed"
            self.after(0,lambda:self.show_preview(label))
        except Exception as exc:
            self.after(0,lambda e=str(exc):self.show_error(e))

    def show_preview(self,label):
        im=Image.open(GENERATED/'preview.png'); self.preview_photo=ImageTk.PhotoImage(im)
        self.preview_label.configure(image=self.preview_photo,text=''); self.status.set(label)

    def show_error(self,error):
        self.status.set("Actie mislukt"); messagebox.showerror("RaceCore",error)


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