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


ROOT = Path(__file__).resolve().parents[2]
APP = Path(__file__).resolve().parent
GENERATED = APP / 'generated'
AUTOSAVE = APP / 'autosave.racecore.json'
LIVE_CONFIG = APP / 'live-link-ui.json'
V18_PATH = ROOT / 'outputs' / 'RaceCore_Studio_v1.8' / 'racecore_studio_v18.py'
V18_AUTOSAVE = V18_PATH.parent / 'autosave.racecore.json'

spec = importlib.util.spec_from_file_location('racecore_v18', V18_PATH)
v18 = importlib.util.module_from_spec(spec)
spec.loader.exec_module(v18)

for module in (
    v18, v18.v17, v18.v17.v16, v18.v17.v16.v15,
    v18.v17.v16.v15.v14, v18.v17.v16.v15.v14.v13,
    v18.v17.v16.v15.v14.v13.v12,
    v18.v17.v16.v15.v14.v13.v12.v11,
):
    module.APP = APP
    module.GENERATED = GENERATED
    module.AUTOSAVE = AUTOSAVE
    module.LIVE_CONFIG = LIVE_CONFIG

COLORS = v18.COLORS
KINDS = ('shape', 'stripe', 'text', 'logo')
GROUP_INFO = {
    'shape': ('Kleurvlakken', 'Vlak'),
    'stripe': ('Strepen & lijnen', 'Streep'),
    'text': ('Tekst & nummers', 'Tekst'),
    'logo': ('Logo’s & sponsors', 'Logo'),
}


class StudioV19(v18.StudioV18):
    def __init__(self):
        migrate = not AUTOSAVE.exists() and V18_AUTOSAVE.exists()
        super().__init__()
        self.title('RaceCore Livery Studio v1.9 - Design Layers')
        if migrate:
            self.load_path(V18_AUTOSAVE, record=False)
            self.autosave()

    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  v1.9')
        toolbar = self.winfo_children()[1]
        for child in toolbar.winfo_children():
            if isinstance(child, tk.Button):
                child.configure(font=('Segoe UI', 8, 'bold'), padx=5)
        tk.Button(
            toolbar, text='Laagoverzicht', command=self.design_layers_dialog,
            font=('Segoe UI', 8, 'bold'), fg=COLORS.NAVY, bg='#93C5FD',
            activebackground='#BFDBFE', relief='flat', padx=6,
        ).pack(side='left', padx=(0, 6), pady=6)

    def apply_state(self, state, record=False):
        super().apply_state(state, record)
        self.refresh_design_layers()

    def collection(self, kind):
        return {
            'shape': self.shape_layers, 'stripe': self.stripe_layers,
            'text': self.text_layers, 'logo': self.logo_layers,
        }[kind]

    def normalise_item(self, kind, item):
        return {
            'shape': self.normalise_shape, 'stripe': self.normalise_stripe,
            'text': self.normalise_text, 'logo': self.normalise_layer,
        }[kind](item)

    def commit_kind(self, kind, select=None, label='Ontwerp bijgewerkt'):
        {
            'shape': self.commit_shapes, 'stripe': self.commit_stripes,
            'text': self.commit_texts, 'logo': self.commit_layers,
        }[kind](select, label)

    def commit_layers(self, select=None, label='Lagen bijgewerkt'):
        super().commit_layers(select, label)
        self.refresh_design_layers(f'logo:{select}' if select is not None else None)

    def commit_stripes(self, select=None, label='Strepen bijgewerkt'):
        super().commit_stripes(select, label)
        self.refresh_design_layers(f'stripe:{select}' if select is not None else None)

    def commit_shapes(self, select=None, label='Kleurvlakken bijgewerkt'):
        super().commit_shapes(select, label)
        self.refresh_design_layers(f'shape:{select}' if select is not None else None)

    def commit_texts(self, select=None, label='Tekst bijgewerkt'):
        super().commit_texts(select, label)
        self.refresh_design_layers(f'text:{select}' if select is not None else None)

    def design_layers_dialog(self):
        win = tk.Toplevel(self)
        win.title('RaceCore Centraal Laagoverzicht')
        win.geometry('1060x680')
        win.minsize(900, 590)
        win.configure(bg=COLORS.PANEL)
        win.transient(self)
        win.grab_set()

        top = tk.Frame(win, bg=COLORS.PANEL)
        top.pack(fill='x', padx=22, pady=(18, 10))
        tk.Label(top, text='CENTRAAL LAAGOVERZICHT', font=('Segoe UI', 15, 'bold'),
                 fg=COLORS.CYAN, bg=COLORS.PANEL).pack(side='left')
        self.design_summary = tk.StringVar()
        tk.Label(top, textvariable=self.design_summary, font=('Segoe UI', 9),
                 fg=COLORS.MUTED, bg=COLORS.PANEL).pack(side='right')

        add_bar = tk.Frame(win, bg='#101F3C')
        add_bar.pack(fill='x', padx=22, pady=(0, 10))
        add_actions = [
            ('+ Kleurvlak', self.add_shape, '#FDE68A'),
            ('+ Streep', self.add_stripe, '#A7F3D0'),
            ('+ Tekst', lambda: self.add_text('team'), '#FDBA74'),
            ('+ Startnummer', lambda: self.add_text('number'), '#FDBA74'),
            ('+ Logo uit bibliotheek', self.open_library_from_layers, '#F9A8D4'),
            ('Sponsorplan', self.open_sponsorplan_from_layers, '#86EFAC'),
        ]
        for title, command, colour in add_actions:
            tk.Button(add_bar, text=title, command=command,
                      font=('Segoe UI', 9, 'bold'), fg=COLORS.NAVY,
                      bg=colour, relief='flat', padx=9, pady=7).pack(
                          side='left', padx=(7, 0), pady=7)

        body = tk.Frame(win, bg=COLORS.PANEL)
        body.pack(fill='both', expand=True, padx=22)
        tree_frame = tk.Frame(body, bg=COLORS.PANEL)
        tree_frame.pack(side='left', fill='both', expand=True)
        self.design_tree = ttk.Treeview(
            tree_frame, columns=('type', 'detail', 'status'), show='tree headings',
            selectmode='browse',
        )
        self.design_tree.heading('#0', text='Laagnaam')
        self.design_tree.heading('type', text='Soort')
        self.design_tree.heading('detail', text='Inhoud')
        self.design_tree.heading('status', text='Status')
        self.design_tree.column('#0', width=260, minwidth=180)
        self.design_tree.column('type', width=105, minwidth=85, anchor='center')
        self.design_tree.column('detail', width=290, minwidth=150)
        self.design_tree.column('status', width=130, minwidth=110, anchor='center')
        scroll = ttk.Scrollbar(tree_frame, orient='vertical', command=self.design_tree.yview)
        self.design_tree.configure(yscrollcommand=scroll.set)
        self.design_tree.pack(side='left', fill='both', expand=True)
        scroll.pack(side='right', fill='y')
        self.design_tree.bind('<Double-Button-1>', lambda _event: self.edit_design_item())
        self.design_tree.bind('<Delete>', lambda _event: self.delete_design_item())
        self.design_tree.bind('<space>', lambda _event: self.toggle_design_item())
        self.design_tree.bind('<Control-d>', lambda _event: self.duplicate_design_item())

        side = tk.Frame(body, bg=COLORS.PANEL, width=195)
        side.pack(side='right', fill='y', padx=(12, 0))
        side.pack_propagate(False)
        actions = [
            ('Visueel bewerken', self.edit_design_item, COLORS.CYAN),
            ('Dupliceren', self.duplicate_design_item, '#334155'),
            ('Naar voren', lambda: self.move_design_item(1), '#334155'),
            ('Naar achteren', lambda: self.move_design_item(-1), '#334155'),
            ('Tonen / verbergen', self.toggle_design_item, '#334155'),
            ('Vergrendelen', self.lock_design_item, '#334155'),
            ('Verwijderen', self.delete_design_item, '#7F1D1D'),
            ('Alles tonen', self.show_all_design_items, '#475569'),
            ('Alles ontgrendelen', self.unlock_all_design_items, '#475569'),
        ]
        for title, command, colour in actions:
            tk.Button(side, text=title, command=command,
                      font=('Segoe UI', 9, 'bold'),
                      fg=(COLORS.NAVY if colour == COLORS.CYAN else '#F8FAFC'),
                      bg=colour, relief='flat', pady=7).pack(fill='x', pady=(0, 5))

        tk.Label(
            win,
            text='Dubbelklik = bewerken  |  Spatie = tonen/verbergen  |  Delete = verwijderen  |  Ctrl+D = dupliceren',
            font=('Segoe UI', 9), fg=COLORS.MUTED, bg=COLORS.PANEL,
        ).pack(anchor='w', padx=22, pady=(8, 0))
        tk.Button(win, text='SLUITEN', command=win.destroy,
                  font=('Segoe UI', 10, 'bold'), fg=COLORS.NAVY,
                  bg=COLORS.CYAN, relief='flat', pady=10).pack(
                      fill='x', padx=22, pady=16)
        self.refresh_design_layers()
        self.design_tree.focus_set()

    def open_library_from_layers(self):
        owner = self.design_tree.winfo_toplevel() if self.live_widget(self, 'design_tree') else None
        if owner:
            owner.destroy()
        self.asset_library_dialog()

    def open_sponsorplan_from_layers(self):
        owner = self.design_tree.winfo_toplevel() if self.live_widget(self, 'design_tree') else None
        if owner:
            owner.destroy()
        self.sponsor_planner()

    def item_detail(self, kind, layer):
        if kind == 'shape':
            return f"{layer['shape']} | {layer['width']} × {layer['height']} px"
        if kind == 'stripe':
            return f"{layer['shape']} | {layer['width']} px breed"
        if kind == 'text':
            return f"‘{layer['text']}’ | {layer['font']}"
        return f"{layer.get('position', 'Nog niet geplaatst')} | {layer.get('scale', 55)}%"

    def refresh_design_layers(self, select=None):
        if not self.live_widget(self, 'design_tree'):
            if hasattr(self, 'design_tree'):
                delattr(self, 'design_tree')
            return
        current = select or (self.design_tree.selection()[0]
                             if self.design_tree.selection() else None)
        self.design_tree.delete(*self.design_tree.get_children())
        total = visible = locked = 0
        for kind in KINDS:
            group_name, type_name = GROUP_INFO[kind]
            collection = self.collection(kind)
            group = self.design_tree.insert('', 'end', iid=f'group:{kind}',
                                            text=f'{group_name} ({len(collection)})',
                                            values=('', '', ''), open=True)
            for index, raw in enumerate(collection):
                layer = self.normalise_item(kind, raw)
                total += 1
                visible += int(layer.get('visible', True))
                locked += int(layer.get('locked', False))
                status = ('Verborgen' if not layer.get('visible', True)
                          else 'Vergrendeld' if layer.get('locked', False)
                          else 'Zichtbaar')
                self.design_tree.insert(
                    group, 'end', iid=f'{kind}:{index}', text=layer.get('name', 'Naamloos'),
                    values=(type_name, self.item_detail(kind, layer), status),
                    tags=(status.lower(),),
                )
        self.design_tree.tag_configure('verborgen', foreground='#94A3B8')
        self.design_tree.tag_configure('vergrendeld', foreground='#FBBF24')
        self.design_summary.set(f'{total} lagen | {visible} zichtbaar | {locked} vergrendeld')
        if current and self.design_tree.exists(current):
            self.design_tree.selection_set(current)
            self.design_tree.focus(current)
            self.design_tree.see(current)

    def selected_design_item(self):
        if not self.live_widget(self, 'design_tree'):
            return None
        selected = self.design_tree.selection()
        if not selected or ':' not in selected[0] or selected[0].startswith('group:'):
            return None
        kind, raw_index = selected[0].split(':', 1)
        try:
            index = int(raw_index)
        except ValueError:
            return None
        collection = self.collection(kind)
        return (kind, index) if 0 <= index < len(collection) else None

    def edit_design_item(self):
        selected = self.selected_design_item()
        if not selected:
            self.status.set('Kies eerst een ontwerplaag')
            return
        kind, index = selected
        layer = self.normalise_item(kind, self.collection(kind)[index])
        if layer.get('locked'):
            self.status.set('Ontgrendel deze laag eerst')
            return
        if kind == 'shape':
            v18.v17.v16.v15.v14.ShapePlacementEditor(self, index)
        elif kind == 'stripe':
            v18.v17.v16.v15.v14.v13.StripePlacementEditor(self, index)
        elif kind == 'text':
            v18.v17.TextPlacementEditor(self, index)
        elif not Path(layer.get('path', '')).exists():
            self.status.set('Het afbeeldingsbestand van deze logo-laag ontbreekt')
        else:
            v18.LogoPlacementEditorV18(self, index)

    def duplicate_design_item(self):
        selected = self.selected_design_item()
        if not selected:
            return
        kind, index = selected
        collection = self.collection(kind)
        layer = copy.deepcopy(self.normalise_item(kind, collection[index]))
        layer['id'] = f"{layer.get('id', kind)}-copy"
        layer['name'] = f"{layer.get('name', 'Laag')} kopie"
        layer['locked'] = False
        if kind in ('shape', 'stripe', 'text'):
            layer['centerX'] = min(4096, layer.get('centerX', 2000) + 70)
            layer['centerY'] = min(4096, layer.get('centerY', 2000) + 70)
        else:
            layer['offsetX'] = layer.get('offsetX', 0) + 70
            layer['offsetY'] = layer.get('offsetY', 0) + 70
        collection.insert(index + 1, layer)
        self.commit_kind(kind, index + 1, 'Laag gedupliceerd')

    def toggle_design_item(self):
        selected = self.selected_design_item()
        if not selected:
            return
        kind, index = selected
        layer = self.normalise_item(kind, self.collection(kind)[index])
        layer['visible'] = not layer.get('visible', True)
        self.commit_kind(kind, index, 'Zichtbaarheid aangepast')

    def lock_design_item(self):
        selected = self.selected_design_item()
        if not selected:
            return
        kind, index = selected
        layer = self.normalise_item(kind, self.collection(kind)[index])
        layer['locked'] = not layer.get('locked', False)
        self.commit_kind(kind, index, 'Vergrendeling aangepast')

    def delete_design_item(self):
        selected = self.selected_design_item()
        if not selected:
            return
        kind, index = selected
        collection = self.collection(kind)
        layer = self.normalise_item(kind, collection[index])
        if layer.get('locked'):
            self.status.set('Een vergrendelde laag kan niet worden verwijderd')
            return
        collection.pop(index)
        self.commit_kind(kind, max(0, index - 1), 'Laag verwijderd')

    def move_design_item(self, delta):
        selected = self.selected_design_item()
        if not selected:
            return
        kind, index = selected
        collection = self.collection(kind)
        layer = self.normalise_item(kind, collection[index])
        if layer.get('locked'):
            self.status.set('Ontgrendel deze laag eerst')
            return
        target = max(0, min(len(collection) - 1, index + delta))
        if target != index:
            collection.insert(target, collection.pop(index))
            self.commit_kind(kind, target, 'Laagvolgorde aangepast')

    def show_all_design_items(self):
        for kind in KINDS:
            for layer in self.collection(kind):
                self.normalise_item(kind, layer)['visible'] = True
        self.refresh_design_layers()
        self.status.set('Alle ontwerplagen zijn zichtbaar')
        self.changed()

    def unlock_all_design_items(self):
        for kind in KINDS:
            for layer in self.collection(kind):
                self.normalise_item(kind, layer)['locked'] = False
        self.refresh_design_layers()
        self.status.set('Alle ontwerplagen zijn ontgrendeld')
        self.changed()


if __name__ == '__main__':
    StudioV19().mainloop()
