"""Always-on-Top-Schnellfenster mit aufklappbaren Schnellmenüs.

Die Leiste schwebt ueber Tibia: Statuspunkt, Play/Pause und beschriftete
Feature-Buttons. Ein Klick auf Cave/Heal/Combo klappt darunter ein
Schnellmenü mit den wichtigsten Aktionen auf (an/aus, Schwellenwerte) —
ohne die Haupt-App oeffnen zu muessen. Position wird per Drag verschoben
und gespeichert.
"""
import customtkinter

from src.ui import livestate, theme
from src.ui.widgets import PercentSlider

BAR_HEIGHT = 66
PANEL_HEIGHTS = {'cavebot': 76, 'healing': 470, 'combo': 170}
WIDTH = 296


class OverlayWindow(customtkinter.CTkToplevel):
    def __init__(self, master, context):
        super().__init__(master)
        self.context = context
        self.overrideredirect(True)
        self.attributes('-topmost', True)
        self.configure(fg_color=theme.SIDEBAR)
        self._drag = None
        self._expanded = None
        self._panelWidgets = []

        position = livestate.loadOverlayPosition()
        if position:
            initial = f'{WIDTH}x{BAR_HEIGHT}+{position[0]}+{position[1]}'
        else:
            screen_x = self.winfo_screenwidth() - WIDTH - 40
            initial = f'{WIDTH}x{BAR_HEIGHT}+{screen_x}+40'
        self.after_idle(lambda: self.geometry(initial))

        self.frame = customtkinter.CTkFrame(
            self, fg_color=theme.SIDEBAR, corner_radius=16,
            border_width=1, border_color=theme.BORDER,
            width=WIDTH, height=BAR_HEIGHT,
        )
        self.frame.pack(fill='x', padx=6, pady=6)
        self.frame.bind('<ButtonPress-1>', self._startDrag)
        self.frame.bind('<B1-Motion>', self._doDrag)
        self.frame.bind('<ButtonRelease-1>', self._endDrag)

        self._buildBar()
        self.panel = None
        self._refresh()

    # ------------------------------------------------------------------ Leiste
    def _buildBar(self):
        bar = customtkinter.CTkFrame(self.frame, fg_color='transparent')
        bar.pack(fill='x', padx=6, pady=5)
        bar.bind('<ButtonPress-1>', self._startDrag)
        bar.bind('<B1-Motion>', self._doDrag)
        bar.bind('<ButtonRelease-1>', self._endDrag)

        self.statusDot = customtkinter.CTkLabel(
            bar, text=theme.ICON_DOT_ON, font=theme.font(15),
            text_color=theme.MUTED, width=18,
        )
        self.statusDot.pack(side='left', padx=(4, 0))

        self.playButton = self._barButton(bar, theme.ICON_PLAY, '', self._togglePlay)
        self.playButton.pack(side='left', padx=2)

        self.featureButtons = {}
        for key, glyph, label in (
            ('cavebot', theme.ICON_CAVEBOT, 'Cave'),
            ('healing', theme.ICON_HEALING, 'Heal'),
            ('combo', theme.ICON_COMBO, 'Combo'),
        ):
            button = self._barButton(
                bar, glyph, label,
                lambda k=key: self._togglePanel(k))
            button.pack(side='left', padx=2)
            self.featureButtons[key] = button

        close = customtkinter.CTkLabel(
            bar, text='✕', font=theme.font(11), text_color=theme.FAINT,
            width=18, cursor='hand2',
        )
        close.pack(side='left', padx=(2, 0))
        close.bind('<Button-1>', lambda _event: self.withdraw())

    def _barButton(self, parent, glyph, label, command):
        wrapper = customtkinter.CTkFrame(parent, fg_color='transparent')
        button = customtkinter.CTkButton(
            wrapper, text=glyph, width=42, height=34, corner_radius=10,
            font=theme.font(14), fg_color=theme.ELEVATED,
            hover_color=theme.BORDER, text_color=theme.MUTED,
            command=command,
        )
        button.pack()
        if label:
            customtkinter.CTkLabel(
                wrapper, text=label, font=theme.font(9),
                text_color=theme.FAINT,
            ).pack()
        wrapper._button = button
        return wrapper

    # ------------------------------------------------------------------ Panels
    def _togglePanel(self, key):
        if self._expanded == key:
            self._expanded = None
        else:
            self._expanded = key
        self._rebuildPanel()
        self._refresh()

    def _rebuildPanel(self):
        for widget in self._panelWidgets:
            widget.destroy()
        self._panelWidgets = []
        if self.panel is not None:
            self.panel.pack_forget()
            self.panel.destroy()
            self.panel = None
        if self._expanded is None:
            self.geometry(f'{WIDTH}x{BAR_HEIGHT + 12}')
            return
        panelHeight = PANEL_HEIGHTS[self._expanded]
        height = BAR_HEIGHT + panelHeight
        self.panel = customtkinter.CTkFrame(
            self, fg_color=theme.SIDEBAR,
            border_width=1, border_color=theme.BORDER,
            corner_radius=12, height=panelHeight - 12,
        )
        self.panel.pack(fill='x', padx=6, pady=(0, 6))
        self.panel.pack_propagate(False)
        self.panel.grid_columnconfigure(0, weight=1)
        self._panelRow = 0
        builder = {
            'cavebot': self._buildCavebotPanel,
            'healing': self._buildHealingPanel,
            'combo': self._buildComboPanel,
        }[self._expanded]
        builder()
        self.after_idle(lambda: self.geometry(f'{WIDTH}x{height}'))

    def _track(self, widget):
        widget.grid(row=self._panelRow, column=0, sticky='ew',
                    padx=4, pady=2)
        self._panelRow += 1
        self._panelWidgets.append(widget)
        return widget

    def _switch(self, parent, label, active, command):
        switch = customtkinter.CTkSwitch(
            parent, text=label, font=theme.font(11),
            progress_color=theme.ACCENT, command=command,
        )
        if active:
            switch.select()
        return self._track(switch)

    def _sliderRow(self, parent, label, value, command, color=theme.ACCENT):
        slider = PercentSlider(
            parent, label, value=value, command=command, color=color)
        return self._track(slider)

    def _buildCavebotPanel(self):
        ctx = self.context.context
        self._switch(self.panel, 'Cavebot aktiviert',
                     ctx['ng_cave']['enabled'],
                     lambda: self.context.toggleCavebot(
                         not ctx['ng_cave']['enabled']))
        self._switch(self.panel, 'Run to Creatures',
                     ctx['ng_cave']['runToCreatures'],
                     lambda: self.context.toggleRunToCreatures(
                         not ctx['ng_cave']['runToCreatures']))

    def _buildHealingPanel(self):
        ctx = self.context.context
        healing = ctx['healing']
        self._switch(self.panel, 'Healing gesamt',
                     self.context.healingMasterEnabled(),
                     lambda: self.context.toggleHealingMaster(
                         not self.context.healingMasterEnabled()))
        separator = customtkinter.CTkLabel(
            self.panel, text='', height=1, fg_color=theme.BORDER)
        self._track(separator)

        potion = healing['potions']['firstHealthPotion']
        self._switch(self.panel, 'Health Potion', potion['enabled'],
                     lambda: self.context.toggleHealingPotionsByKey(
                         'firstHealthPotion', not potion['enabled']))
        self._sliderRow(self.panel, 'bei HP ≤ %',
                        potion['hpPercentageLessThanOrEqual'],
                        lambda v: self.context.setHealthPotionHpPercentageLessThanOrEqual(
                            'firstHealthPotion', v))

        mana = healing['potions']['firstManaPotion']
        self._switch(self.panel, 'Mana Potion', mana['enabled'],
                     lambda: self.context.toggleManaPotionsByKey(
                         'firstManaPotion', not mana['enabled']))
        self._sliderRow(self.panel, 'bei Mana ≤ %',
                        mana['manaPercentageLessThanOrEqual'],
                        lambda v: self.context.setHealthPotionManaPercentageLessThanOrEqual(
                            'firstManaPotion', v))

        light = healing['spells']['lightHealing']
        self._switch(self.panel, 'Exura (light)', light['enabled'],
                     lambda: self.context.toggleSpellByKey(
                         'lightHealing', not light['enabled']))
        self._sliderRow(self.panel, 'bei HP ≤ %',
                        light['hpPercentageLessThanOrEqual'],
                        lambda v: self.context.setSpellHpPercentageLessThanOrEqual(
                            'lightHealing', v))

        critical = healing['spells']['criticalHealing']
        self._switch(self.panel, 'Exura Gran (kritisch)', critical['enabled'],
                     lambda: self.context.toggleSpellByKey(
                         'criticalHealing', not critical['enabled']))
        self._sliderRow(self.panel, 'bei HP ≤ %',
                        critical['hpPercentageLessThanOrEqual'],
                        lambda v: self.context.setSpellHpPercentageLessThanOrEqual(
                            'criticalHealing', v))

        utura = healing['spells']['utura']
        self._switch(self.panel, 'Utura', utura['enabled'],
                     lambda: self.context.toggleSpellByKey(
                         'utura', not utura['enabled']))
        food = healing['eatFood']
        self._switch(self.panel, 'Food essen', food['enabled'],
                     lambda: self.context.toggleFoodByKey(
                         not food['enabled']))

    def _buildComboPanel(self):
        ctx = self.context.context
        combos = ctx['ng_comboSpells']
        self._switch(self.panel, 'Kombos gesamt', combos['enabled'],
                     lambda: self.context.toggleComboSpells(
                         not combos['enabled']))
        for index, combo in enumerate(combos['items'][:4]):
            self._switch(self.panel, combo['name'], combo['enabled'],
                         lambda i=index, c=combo:
                         self.context.toggleSingleCombo(not c['enabled'], i))

    # ------------------------------------------------------------------ Drag
    def _startDrag(self, event):
        self._drag = (event.x, event.y)

    def _doDrag(self, event):
        if not self._drag:
            return
        x = self.winfo_x() + event.x - self._drag[0]
        y = self.winfo_y() + event.y - self._drag[1]
        self.geometry(f'+{x}+{y}')

    def _endDrag(self, _event):
        self._drag = None
        livestate.saveOverlayPosition(self.winfo_x(), self.winfo_y())

    # ------------------------------------------------------------------ Aktionen
    def _togglePlay(self):
        if self.context.context['ng_pause']:
            self.context.play()
        else:
            self.context.pause()
        self._refresh()

    # ------------------------------------------------------------------ Refresh
    def _refresh(self):
        ctx = self.context.context
        paused = ctx['ng_pause']
        if 'ng_failsafe' in ctx:
            dot = theme.DANGER
        elif paused and ctx.get('ng_sessionBreak'):
            dot = theme.WARNING
        elif paused:
            dot = theme.MUTED
        else:
            dot = theme.SUCCESS
        self.statusDot.configure(text_color=dot)
        self.playButton._button.configure(
            text=theme.ICON_PAUSE if not paused else theme.ICON_PLAY,
            fg_color=theme.ACCENT if not paused else theme.ELEVATED,
            text_color='#FFFFFF' if not paused else theme.MUTED,
        )
        states = {
            'cavebot': ctx['ng_cave']['enabled'],
            'healing': self.context.healingMasterEnabled(),
            'combo': ctx['ng_comboSpells']['enabled'],
        }
        for key, active in states.items():
            expanded = self._expanded == key
            self.featureButtons[key]._button.configure(
                fg_color=theme.ACCENT if expanded else (
                    theme.ACCENT_SOFT if active else theme.ELEVATED),
                text_color='#FFFFFF' if expanded else (
                    theme.ACCENT if active else theme.MUTED),
            )
        self.after(800, self._refresh)
