#!/usr/bin/env python3
import os
import shlex
import subprocess
from pathlib import Path

import gi

gi.require_version("Gtk", "3.0")
gi.require_version("Gdk", "3.0")
from gi.repository import Gdk, Gtk  # noqa: E402


HYPR_DIR = Path.home() / ".config" / "hypr"
THEME_DIR = HYPR_DIR / "Themes"
CURRENT_WALLPAPER = HYPR_DIR / "current-wallpaper"


DEFAULT_THEME = {
    "NAME": "Power",
    "ACCENT": "#f38ba8",
    "ACCENT_2": "#cba6f7",
    "BACKGROUND_HEX": "#18141f",
    "PANEL_HEX": "#313244",
    "FOREGROUND": "#f5e0dc",
    "MUTED": "#a6adc8",
    "SELECTED_TEXT": "#11111b",
}


def parse_theme_file(path):
    theme = {}

    for line in path.read_text(encoding="utf-8", errors="ignore").splitlines():
        line = line.strip()
        if not line or line.startswith("#") or "=" not in line:
            continue

        key, value = line.split("=", 1)
        key = key.strip()
        value = value.strip()

        try:
            parsed = shlex.split(value)
            theme[key] = parsed[0] if parsed else ""
        except ValueError:
            theme[key] = value.strip("\"'")

    return theme


def load_current_theme():
    current_wallpaper = ""
    if CURRENT_WALLPAPER.exists():
        current_wallpaper = CURRENT_WALLPAPER.read_text(encoding="utf-8", errors="ignore").strip()

    for theme_file in sorted(THEME_DIR.glob("*.theme")):
        theme = parse_theme_file(theme_file)
        if theme.get("WALLPAPER") == current_wallpaper:
            return {**DEFAULT_THEME, **theme}

    rose = THEME_DIR / "rose-night.theme"
    if rose.exists():
        return {**DEFAULT_THEME, **parse_theme_file(rose)}

    return DEFAULT_THEME


def run(command):
    subprocess.Popen(command, start_new_session=True)
    Gtk.main_quit()


class PowerMenu(Gtk.Window):
    def __init__(self):
        super().__init__(title="Power")

        self.theme = load_current_theme()
        self.set_decorated(False)
        self.set_resizable(False)
        self.set_keep_above(True)
        self.set_position(Gtk.WindowPosition.CENTER)
        self.set_type_hint(Gdk.WindowTypeHint.DIALOG)
        self.set_skip_taskbar_hint(True)
        self.set_skip_pager_hint(True)
        self.set_app_paintable(True)
        self.connect("key-press-event", self.on_key_press)
        self.connect("focus-out-event", lambda *_: Gtk.main_quit())

        overlay = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=18)
        overlay.get_style_context().add_class("power-shell")

        title = Gtk.Label(label=self.theme.get("NAME", "Power"))
        title.get_style_context().add_class("power-title")
        overlay.pack_start(title, False, False, 0)

        grid = Gtk.Grid()
        grid.set_column_spacing(14)
        grid.set_row_spacing(14)
        grid.set_halign(Gtk.Align.CENTER)

        actions = [
            ("", "Sperren", ["hyprlock"]),
            ("󰤄", "Ruhezustand", ["systemctl", "suspend"]),
            ("󰗽", "Abmelden", ["hyprctl", "dispatch", "exit"]),
            ("󰜉", "Neustart", ["systemctl", "reboot"]),
            ("⏻", "Ausschalten", ["systemctl", "poweroff"]),
            ("󰗼", "Abbrechen", None),
        ]

        for index, (icon, label, command) in enumerate(actions):
            button = self.make_button(icon, label, command)
            grid.attach(button, index % 3, index // 3, 1, 1)

        overlay.pack_start(grid, False, False, 0)
        self.add(overlay)
        self.apply_css()

    def make_button(self, icon, label, command):
        button = Gtk.Button()
        button.get_style_context().add_class("power-button")
        button.set_size_request(150, 118)
        button.set_relief(Gtk.ReliefStyle.NONE)

        box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=8)
        box.set_halign(Gtk.Align.CENTER)
        box.set_valign(Gtk.Align.CENTER)

        icon_label = Gtk.Label(label=icon)
        icon_label.get_style_context().add_class("power-icon")
        text_label = Gtk.Label(label=label)
        text_label.get_style_context().add_class("power-label")

        box.pack_start(icon_label, False, False, 0)
        box.pack_start(text_label, False, False, 0)
        button.add(box)

        if command:
            button.connect("clicked", lambda *_: run(command))
        else:
            button.connect("clicked", lambda *_: Gtk.main_quit())

        return button

    def apply_css(self):
        css = f"""
        window {{
            background: transparent;
        }}

        .power-shell {{
            margin: 0;
            padding: 24px;
            border-radius: 26px;
            border: 1px solid {self.theme["ACCENT"]};
            background: alpha({self.theme["BACKGROUND_HEX"]}, 0.94);
            box-shadow: 0 22px 70px alpha(#000000, 0.55);
        }}

        .power-title {{
            color: {self.theme["FOREGROUND"]};
            font-family: "JetBrainsMono Nerd Font", "JetBrains Mono", sans-serif;
            font-size: 18px;
            font-weight: 800;
        }}

        .power-button {{
            color: {self.theme["FOREGROUND"]};
            background: alpha({self.theme["PANEL_HEX"]}, 0.82);
            border: 1px solid alpha({self.theme["ACCENT_2"]}, 0.42);
            border-radius: 18px;
            transition: 160ms ease;
        }}

        .power-button:hover,
        .power-button:focus {{
            color: {self.theme["SELECTED_TEXT"]};
            background: linear-gradient(135deg, {self.theme["ACCENT"]}, {self.theme["ACCENT_2"]});
            border-color: {self.theme["ACCENT"]};
        }}

        .power-icon {{
            font-family: "JetBrainsMono Nerd Font", "JetBrains Mono", sans-serif;
            font-size: 34px;
            font-weight: 800;
        }}

        .power-label {{
            font-family: "JetBrainsMono Nerd Font", "JetBrains Mono", sans-serif;
            font-size: 13px;
            font-weight: 800;
        }}
        """

        provider = Gtk.CssProvider()
        provider.load_from_data(css.encode("utf-8"))
        Gtk.StyleContext.add_provider_for_screen(
            Gdk.Screen.get_default(),
            provider,
            Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION,
        )

    def on_key_press(self, _widget, event):
        if event.keyval in (Gdk.KEY_Escape, Gdk.KEY_q):
            Gtk.main_quit()


if __name__ == "__main__":
    window = PowerMenu()
    window.show_all()
    Gtk.main()
