#!/usr/bin/env python3
"""RaveOS Update Indicator — tálca-jelző.

Önálló (DE-független) tálca-alkalmazás. A /var/lib/raveos-updater/status.json
fájlt olvassa, amit a háttérszolgáltatás (check.py + systemd timer) állít elő.
A jobb felső tálcán egy ikon mutatja, ha van elérhető RaveOS frissítés.

Első verzió: GNOME (Qt6 SNI tálca az AppIndicator kiegészítővel).
Később Plasma/Hyprland/COSMIC is ugyanezt a status.json-t használja.
"""

import json
import os
import shlex
import shutil
import subprocess
import sys

from PyQt6.QtCore import Qt, QTimer
from PyQt6.QtGui import QAction, QBrush, QColor, QFont, QIcon, QPainter, QPen, QPixmap
from PyQt6.QtWidgets import QApplication, QMenu, QSystemTrayIcon

STATUS_FILE = "/var/lib/raveos-updater/status.json"
CHECK_CMD = "/usr/lib/raveos-updater/check.py"
APP_NAME = "RaveOS Update Indicator"


def read_status():
    try:
        with open(STATUS_FILE, encoding="utf-8") as f:
            return json.load(f)
    except Exception:
        return None


def make_icon(count):
    pm = QPixmap(64, 64)
    pm.fill(Qt.GlobalColor.transparent)
    p = QPainter(pm)
    p.setRenderHint(QPainter.RenderHint.Antialiasing)

    if count:
        p.setBrush(QBrush(QColor("#23e06b")))
        p.setPen(QPen(QColor("#12833c"), 3))
    else:
        p.setBrush(QBrush(QColor("#5a5a5a")))
        p.setPen(QPen(QColor("#3a3a3a"), 3))
    p.drawEllipse(6, 6, 52, 52)

    p.setPen(QColor("#ffffff"))
    if count:
        font = QFont()
        font.setBold(True)
        font.setPixelSize(30)
        p.setFont(font)
        p.drawText(pm.rect(), Qt.AlignmentFlag.AlignCenter, str(count) if count < 100 else "99")
    else:
        pen = QPen(QColor("#ffffff"), 7)
        pen.setCapStyle(Qt.PenCapStyle.RoundCap)
        pen.setJoinStyle(Qt.PenJoinStyle.RoundJoin)
        p.setPen(pen)
        p.drawLine(18, 33, 28, 43)
        p.drawLine(28, 43, 47, 20)
    p.end()
    return QIcon(pm)


def spawn_terminal(cmd):
    candidates = [
        ["kgx", "-e", "bash", "-c", cmd],
        ["gnome-terminal", "--", "bash", "-c", cmd],
        ["konsole", "-e", "bash", "-c", cmd],
        ["xterm", "-e", "bash", "-c", cmd],
    ]
    for c in candidates:
        if shutil.which(c[0]):
            subprocess.Popen(c, start_new_session=True)
            return True
    return False


class Updater:
    def __init__(self, app):
        self.app = app
        self.tray = QSystemTrayIcon()
        self.tray.setToolTip(APP_NAME)
        self.menu = QMenu()
        self.tray.setContextMenu(self.menu)
        self.refresh()
        self.tray.show()
        # Qt6 SNI: a tálca-ikon regisztrációjához legalább egy esemény-hurok
        # iteráció kell, különben GNOME-on nem jelenik meg az ikon.
        self.app.processEvents()

        self.timer = QTimer()
        self.timer.timeout.connect(self.refresh)
        self.timer.start(60_000)

    def refresh(self):
        st = read_status()
        self.menu.clear()

        if st is None:
            self.tray.setIcon(make_icon(0))
            self._add("RaveOS állapot ismeretlen", enabled=False)
            self._add("(az ellenőrzés még nem futott le)", enabled=False)
        elif st.get("error"):
            self.tray.setIcon(make_icon(0))
            self._add("RaveOS ellenőrzés sikertelen", enabled=False)
            self._add(st["error"], enabled=False)
        else:
            count = st.get("count", 0)
            self.tray.setIcon(make_icon(count))
            if count:
                self._add(f"{count} RaveOS frissítés elérhető", enabled=False)
                self.tray.setToolTip(f"{APP_NAME}: {count} frissítés elérhető")
                self.menu.addSeparator()
                for u in st.get("updates", []):
                    self._add(f"{u['name']}  {u['old']} → {u['new']}", enabled=False)
            else:
                self._add("RaveOS naprakész", enabled=False)
                self.tray.setToolTip(f"{APP_NAME}: naprakész")
            checked = st.get("checked", "")
            if checked:
                self._add("Ellenőrizve: " + checked.replace("T", " ")[:16], enabled=False)

        self.menu.addSeparator()
        self._add("Frissítés most", self._update_now)
        self._add("Ellenőrzés most", self._check_now)
        self._add("Kilépés", self.app.quit)

    def _add(self, text, callback=None, enabled=True):
        act = QAction(text, self.menu)
        act.setEnabled(enabled)
        if callback:
            act.triggered.connect(callback)
        self.menu.addAction(act)
        return act

    def _update_now(self):
        spawn_terminal("rave upgrade; exec bash")

    def _check_now(self):
        if shutil.which("pkexec"):
            subprocess.Popen(["pkexec", CHECK_CMD], start_new_session=True)
        else:
            subprocess.Popen(["sudo", CHECK_CMD], start_new_session=True)


def main():
    app = QApplication(sys.argv)
    app.setApplicationName(APP_NAME)
    app.setQuitOnLastWindowClosed(False)

    if not QSystemTrayIcon.isSystemTrayAvailable():
        print("RaveOS Update Indicator: nincs elérhető tálca (SNI) a jelenlegi környezetben.",
              file=sys.stderr)

    Updater(app)
    sys.exit(app.exec())


if __name__ == "__main__":
    main()
