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


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'
V20_PATH = ROOT / 'outputs' / 'RaceCore_Studio_v2.0' / 'racecore_studio_v20.py'
V20_AUTOSAVE = V20_PATH.parent / 'autosave.racecore.json'

spec = importlib.util.spec_from_file_location('racecore_v20', V20_PATH)
v20 = importlib.util.module_from_spec(spec)
spec.loader.exec_module(v20)

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

COLORS = v20.COLORS
TEMPLATE_ENGINE = v20.v19.v18.v17.v16.v15

SMART_STYLES = {
    'Clean & professioneel': (
        'Clean GT',
        'Rustige vlakken en dunne lijnen. Veel vrije ruimte voor teamnaam en sponsors.',
    ),
    'Factory race': (
        'Factory Racing',
        'Een stevig fabrieksontwerp met duidelijke kleurvlakken en race-accenten.',
    ),
    'Agressief & schuin': (
        'Bold Diagonal',
        'Schuine vormen en krachtige lijnen voor een moderne, snelle uitstraling.',
    ),
    'Centraal & strak': (
        'Center Focus',
        'De aandacht ligt op motorkap en dak, terwijl de zijkanten rustig blijven.',
    ),
}

# De twee grote deur-eilanden zijn in de Ferrari-UV niet exact rond het midden
# gespiegeld. Deze as is op de echte 4096px-template gekalibreerd.
SMART_DOOR_PAIR_AXIS = 4880


def expand_smart_door_pairs(layers):
    expanded = []
    for raw in layers:
        layer = copy.deepcopy(raw)
        if not layer.get('paired'):
            layer['smartStart'] = True
            expanded.append(layer)
            continue
        base_id = str(layer.get('id', 'smart-layer'))
        base_name = str(layer.get('name', 'Ontwerplaag'))
        left = copy.deepcopy(layer)
        left.update({
            'id': f'{base_id}-left', 'name': f'{base_name} - deur links',
            'paired': False, 'smartStart': True, 'smartDoor': 'left',
        })
        right = copy.deepcopy(layer)
        right.update({
            'id': f'{base_id}-right', 'name': f'{base_name} - deur rechts',
            'paired': False, 'smartStart': True, 'smartDoor': 'right',
            'centerY': max(0, min(4096, SMART_DOOR_PAIR_AXIS - int(layer['centerY']))),
            'rotation': float(layer.get('rotation', 0)) + 180,
        })
        expanded.extend((left, right))
    return expanded


def smart_design_layers(style, accent, detail, team_name='', place_team=False):
    template_name = SMART_STYLES.get(style, SMART_STYLES['Clean & professioneel'])[0]
    shapes, stripes = TEMPLATE_ENGINE.template_layers(template_name, accent, detail)
    # Houd lijnensets weg van de centrale sponsor- en nummerzone. De oorspronkelijke
    # templates waren bedoeld als losse voorbeelden en liepen door tekst heen.
    for stripe in stripes:
        if stripe.get('paired'):
            stripe['centerY'] = 1540
            stripe['width'] = min(int(stripe.get('width', 40)), 46)
            stripe['gap'] = min(int(stripe.get('gap', 42)), 38)
    shapes = expand_smart_door_pairs(shapes)
    stripes = expand_smart_door_pairs(stripes)
    texts = []
    team_name = team_name.strip()

    if place_team and team_name:
        team_layer = {
            'id': 'smart-team-name', 'name': 'Teamnaam zijkanten',
            'text': team_name.upper(), 'font': 'Modern Bold',
            'colour': detail, 'outlineColour': '#08152C',
            'fontSize': 92, 'outlineWidth': 4, 'rotation': 0,
            'centerX': 2050, 'centerY': 1390, 'opacity': 100,
            'paired': True, 'visible': True, 'locked': False,
        }
        texts.extend(expand_smart_door_pairs([team_layer]))
    return shapes, stripes, texts


class StudioV21(v20.StudioV20):
    def __init__(self):
        migrate = not AUTOSAVE.exists() and V20_AUTOSAVE.exists()
        super().__init__()
        self.title('RaceCore Livery Studio v2.1 - Slimme Start')
        if migrate:
            self.load_path(V20_AUTOSAVE, record=False)
            self.autosave()
        if self.repair_legacy_smart_start():
            self.autosave()
            self.status.set('Slimme Start-opmaak automatisch opgeschoond')

    def repair_legacy_smart_start(self):
        legacy_ids = {'smart-number-side', 'smart-number-hood'}
        legacy_found = any(
            str(layer.get('id', '')) in legacy_ids for layer in self.text_layers
        )
        legacy_team = any(
            str(layer.get('id', '')) == 'smart-team-name' and layer.get('paired')
            for layer in self.text_layers
        )
        if not legacy_found and not legacy_team:
            return False
        self.text_layers = [
            layer for layer in self.text_layers
            if str(layer.get('id', '')) not in legacy_ids
        ]
        repaired_texts = []
        for layer in self.text_layers:
            if str(layer.get('id', '')) == 'smart-team-name':
                layer['fontSize'] = 92
                layer['outlineWidth'] = 4
                layer['centerY'] = 1390
                repaired_texts.extend(expand_smart_door_pairs([layer]))
            else:
                repaired_texts.append(layer)
        self.text_layers = repaired_texts
        for stripe in self.stripe_layers:
            if stripe.get('paired') and str(stripe.get('id', '')).startswith('template-stripe-'):
                stripe['centerY'] = 1540
                stripe['width'] = min(int(stripe.get('width', 40)), 46)
                stripe['gap'] = min(int(stripe.get('gap', 42)), 38)
        repaired_shapes = []
        for layer in self.shape_layers:
            if (layer.get('paired') and
                    str(layer.get('id', '')).startswith('template-shape-')):
                repaired_shapes.extend(expand_smart_door_pairs([layer]))
            else:
                repaired_shapes.append(layer)
        repaired_stripes = []
        for layer in self.stripe_layers:
            if (layer.get('paired') and
                    str(layer.get('id', '')).startswith('template-stripe-')):
                repaired_stripes.extend(expand_smart_door_pairs([layer]))
            else:
                repaired_stripes.append(layer)
        self.shape_layers = repaired_shapes
        self.stripe_layers = repaired_stripes
        return True

    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  v2.1')
        toolbar = self.winfo_children()[1]
        smart_button = tk.Button(
            toolbar, text='SLIMME START', command=self.smart_start_dialog,
            font=('Segoe UI', 9, 'bold'), fg=COLORS.NAVY, bg='#86EFAC',
            activebackground='#BBF7D0', relief='flat', padx=12,
            cursor='hand2',
        )
        before = self.toolbar_menus[0][0] if self.toolbar_menus else None
        smart_button.pack(side='left', padx=(7, 0), pady=6, before=before)
        if self.toolbar_menus:
            design_menu = self.toolbar_menus[0][1]
            design_menu.insert_command(
                0, label='Slimme start-assistent', command=self.smart_start_dialog
            )
            design_menu.insert_separator(1)

    def smart_start_dialog(self):
        win = tk.Toplevel(self)
        win.title('RaceCore Slimme Start')
        win.geometry('940x680')
        win.minsize(860, 620)
        win.configure(bg=COLORS.PANEL)
        win.transient(self)
        win.grab_set()

        top = tk.Frame(win, bg=COLORS.PANEL)
        top.pack(fill='x', padx=24, pady=(18, 12))
        tk.Label(
            top, text='SLIMME START', font=('Segoe UI', 17, 'bold'),
            fg=COLORS.CYAN, bg=COLORS.PANEL,
        ).pack(anchor='w')
        tk.Label(
            top,
            text='Kies de uitstraling en vul je teamgegevens in. RaceCore maakt daarna een complete, bewerkbare basislivery.',
            font=('Segoe UI', 9), fg=COLORS.MUTED, bg=COLORS.PANEL,
            wraplength=850, justify='left',
        ).pack(anchor='w', pady=(4, 0))

        content = tk.Frame(win, bg=COLORS.PANEL)
        content.pack(fill='both', expand=True, padx=24)
        left = tk.Frame(content, bg='#08152C', width=420)
        left.pack(side='left', fill='both', expand=True, padx=(0, 12))
        right = tk.Frame(content, bg='#101F3C', width=390)
        right.pack(side='right', fill='both', expand=True)

        tk.Label(
            left, text='1  KIES DE STIJL', font=('Segoe UI', 11, 'bold'),
            fg='#86EFAC', bg='#08152C',
        ).pack(anchor='w', padx=18, pady=(17, 8))
        selected_style = tk.StringVar(value='Clean & professioneel')
        style_description = tk.StringVar(value=SMART_STYLES[selected_style.get()][1])

        def choose_style():
            style_description.set(SMART_STYLES[selected_style.get()][1])

        for name in SMART_STYLES:
            tk.Radiobutton(
                left, text=name, value=name, variable=selected_style,
                command=choose_style, font=('Segoe UI', 10, 'bold'),
                fg=COLORS.TEXT, bg='#08152C', selectcolor='#253656',
                activebackground='#08152C', activeforeground=COLORS.TEXT,
                anchor='w', padx=6, pady=5,
            ).pack(fill='x', padx=14)
        tk.Label(
            left, textvariable=style_description, font=('Segoe UI', 9),
            fg='#BFDBFE', bg='#08152C', wraplength=360, justify='left',
        ).pack(anchor='w', padx=20, pady=(12, 10))
        tk.Frame(left, bg='#1E3A5F', height=1).pack(fill='x', padx=18, pady=8)
        tk.Label(
            left, text='Je krijgt losse kleurvlakken, strepen en teksten. Alles blijft achteraf verplaatsbaar en verwijderbaar.',
            font=('Segoe UI', 9), fg=COLORS.MUTED, bg='#08152C',
            wraplength=360, justify='left',
        ).pack(anchor='w', padx=20, pady=8)

        tk.Label(
            right, text='2  KLEUREN & IDENTITEIT', font=('Segoe UI', 11, 'bold'),
            fg='#FDE68A', bg='#101F3C',
        ).pack(anchor='w', padx=18, pady=(17, 8))
        base_colour = tk.StringVar(value=self.primary.get())
        accent_colour = tk.StringVar(value='#22D3EE')
        detail_colour = tk.StringVar(value='#FFFFFF')

        def colour_row(label, variable):
            row = tk.Frame(right, bg='#101F3C')
            row.pack(fill='x', padx=18, pady=4)
            tk.Label(
                row, text=label, font=('Segoe UI', 9),
                fg=COLORS.TEXT, bg='#101F3C',
            ).pack(side='left')
            button = tk.Button(
                row, textvariable=variable, font=('Consolas', 9, 'bold'),
                width=10, relief='flat', cursor='hand2',
            )
            button.pack(side='right')

            def choose_colour():
                value = colorchooser.askcolor(variable.get(), title=label)[1]
                if value:
                    variable.set(value.upper())
                    self.set_colour_button(button, variable.get())

            button.configure(command=choose_colour)
            self.set_colour_button(button, variable.get())

        colour_row('Basiskleur', base_colour)
        colour_row('Hoofdkleur ontwerp', accent_colour)
        colour_row('Tekst en contrast', detail_colour)

        tk.Label(right, text='Teamnaam (optioneel)', font=('Segoe UI', 9),
                 fg=COLORS.TEXT, bg='#101F3C').pack(anchor='w', padx=18,
                                                   pady=(14, 3))
        team_name = tk.StringVar(value='RACECORE RACING')
        tk.Entry(
            right, textvariable=team_name, font=('Segoe UI', 10),
            bg='#E2E8F0', fg='#0F172A', relief='flat',
        ).pack(fill='x', padx=18, ipady=6)

        place_team = tk.BooleanVar(value=False)
        keep_logos = tk.BooleanVar(value=True)
        sponsor_next = tk.BooleanVar(value=False)
        for label, variable in (
            ('Teamnaam direct op beide zijkanten plaatsen', place_team),
            ('Bestaande logo-lagen behouden', keep_logos),
            ('Hierna meteen sponsors verdelen', sponsor_next),
        ):
            tk.Checkbutton(
                right, text=label, variable=variable,
                font=('Segoe UI', 9), fg=COLORS.TEXT, bg='#101F3C',
                selectcolor='#253656', activebackground='#101F3C',
                activeforeground=COLORS.TEXT,
            ).pack(anchor='w', padx=14, pady=(9, 0))

        tk.Label(
            right,
            text='LMU-nummerplaten en officiële autostickers blijven beschermd. Slimme Start zet daarom geen los startnummer over de body.',
            font=('Segoe UI', 8), fg='#BFDBFE', bg='#101F3C',
            wraplength=340, justify='left',
        ).pack(anchor='w', padx=18, pady=(11, 0))

        form_message = tk.StringVar()
        tk.Label(
            right, textvariable=form_message, font=('Segoe UI', 9, 'bold'),
            fg='#FCA5A5', bg='#101F3C', wraplength=340, justify='left',
        ).pack(anchor='w', padx=18, pady=(10, 0))

        def apply_smart_design():
            team = team_name.get().strip()[:28] or 'RACECORE RACING'
            shapes, stripes, texts = smart_design_layers(
                selected_style.get(), accent_colour.get(), detail_colour.get(),
                team, place_team.get(),
            )
            self.loading = True
            self.blank_mode = True
            self.primary.set(base_colour.get())
            self.accent.set(detail_colour.get())
            self.width.set(100)
            self.preset.set('Geen strepen')
            self.shape_layers = [self.normalise_shape(item) for item in shapes]
            self.stripe_layers = [self.normalise_stripe(item) for item in stripes]
            self.text_layers = [self.normalise_text(item) for item in texts]
            if not keep_logos.get():
                self.logo_layers = []
            self.loading = False
            self.refresh_main_colours()
            for method_name in (
                'refresh_shapes', 'refresh_stripes', 'refresh_texts',
                'refresh_layers', 'refresh_design_layers',
            ):
                method = getattr(self, method_name, None)
                if method:
                    method()
            open_sponsors = sponsor_next.get()
            win.destroy()
            self.changed()
            self.status.set(
                f'Slimme start klaar: {selected_style.get()}'
            )
            if open_sponsors:
                self.after(150, self.sponsor_planner)

        actions = tk.Frame(win, bg=COLORS.PANEL)
        actions.pack(fill='x', padx=24, pady=18)
        tk.Button(
            actions, text='ANNULEREN', command=win.destroy,
            font=('Segoe UI', 9, 'bold'), fg=COLORS.TEXT,
            bg='#475569', relief='flat', pady=10,
        ).pack(side='left', fill='x', expand=True, padx=(0, 5))
        tk.Button(
            actions, text='MAAK MIJN BASISLIVERY', command=apply_smart_design,
            font=('Segoe UI', 10, 'bold'), fg=COLORS.NAVY,
            bg='#86EFAC', activebackground='#BBF7D0',
            relief='flat', pady=10,
        ).pack(side='left', fill='x', expand=True, padx=(5, 0))


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