#!/usr/bin/env python3
# FWS — fenêtre « À propos » : deux onglets, « Le projet FWS » (ce qu'est FWS,
# version, liens) et « Système » (matériel + logiciel détectés). Remplace le
# « About Xfce » de libxfce4ui par une page de marque FWS. GTK3 (python-gobject
# installé avec le bureau).

import os
import re
import subprocess

import gi

gi.require_version("Gtk", "3.0")
gi.require_version("Gdk", "3.0")  # sinon gi charge Gdk 4.0 (conflit avec Gtk3)
from gi.repository import Gdk, GLib, Gtk  # noqa: E402

GLib.set_prgname("fws-about")


def _osrelease():
    data = {}
    for path in ("/etc/os-release", "/usr/lib/os-release"):
        try:
            with open(path) as fh:
                for line in fh:
                    m = re.match(r'^([A-Z_]+)=(.*)$', line.strip())
                    if m:
                        data[m.group(1)] = m.group(2).strip('"')
            break
        except OSError:
            continue
    return data


def _cmd(*argv):
    try:
        return subprocess.check_output(argv, text=True,
                                       stderr=subprocess.DEVNULL).strip()
    except (OSError, subprocess.CalledProcessError):
        return ""


def _cpu():
    try:
        with open("/proc/cpuinfo") as fh:
            for line in fh:
                if line.startswith("model name"):
                    return line.split(":", 1)[1].strip()
    except OSError:
        pass
    return "inconnu"


def _mem():
    try:
        with open("/proc/meminfo") as fh:
            for line in fh:
                if line.startswith("MemTotal"):
                    kib = int(line.split()[1])
                    return f"{kib / 1048576:.1f} Gio"
    except OSError:
        pass
    return "inconnu"


def _gpus():
    out = []
    for line in _cmd("lspci").splitlines():
        low = line.lower()
        if "vga" in low or "3d" in low or "display" in low:
            out.append(line.split(":", 2)[-1].strip())
    return out or ["inconnu"]


def _desktop():
    if os.environ.get("HYPRLAND_INSTANCE_SIGNATURE"):
        return "Hyprland"
    env = os.environ.get("XDG_CURRENT_DESKTOP") \
        or os.environ.get("DESKTOP_SESSION") or ""
    return env or "inconnu"


def _session_type():
    t = os.environ.get("XDG_SESSION_TYPE", "")
    return {"wayland": "Wayland", "x11": "X11"}.get(t, t or "inconnu")


def _disks():
    out = []
    for line in _cmd("lsblk", "-dno", "NAME,SIZE,MODEL,TYPE").splitlines():
        f = line.split()
        if f and f[-1] == "disk":
            out.append(" ".join(f[:-1]))
    return out or ["inconnu"]


def _grid(rows):
    grid = Gtk.Grid(column_spacing=18, row_spacing=8, margin=18)
    for i, (key, val) in enumerate(rows):
        k = Gtk.Label(xalign=1)
        k.set_markup(f"<b>{GLib.markup_escape_text(key)}</b>")
        k.get_style_context().add_class("dim-label")
        v = Gtk.Label(label=val, xalign=0, selectable=True)
        v.set_line_wrap(True)
        grid.attach(k, 0, i, 1, 1)
        grid.attach(v, 1, i, 1, 1)
    return grid


def _project_tab(osr):
    box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=10, margin=20)
    title = Gtk.Label()
    name = osr.get("PRETTY_NAME") or osr.get("NAME") or "FWS Linux"
    title.set_markup(f"<span size='xx-large' weight='bold'>{name}</span>")
    box.pack_start(title, False, False, 0)

    tag = Gtk.Label(label="Une distribution Linux pensée pour remplacer "
                          "Windows : bureau prêt à l'emploi, jeux, VR et "
                          "compatibilité applicative.")
    tag.set_line_wrap(True)
    tag.set_max_width_chars(52)
    box.pack_start(tag, False, False, 0)

    feats = Gtk.Label()
    feats.set_markup(
        "<b>Inclus :</b>  installateur graphique · plusieurs bureaux "
        "(GNOME, KDE, Hyprland, i3, XFCE) · Steam &amp; Proton-GE · "
        "réalité virtuelle (SteamVR) · winboat (applications Windows) · "
        "pare-feu · réparation système intégrée.")
    feats.set_line_wrap(True)
    feats.set_max_width_chars(52)
    feats.set_xalign(0)
    box.pack_start(feats, False, False, 6)

    home = osr.get("HOME_URL") or "https://github.com/You-re-like-Windows-a-bitch/fws"
    link = Gtk.LinkButton.new_with_label(home, "Site du projet")
    box.pack_start(link, False, False, 0)
    return box


def _system_tab(osr):
    rows = [
        ("Système", osr.get("PRETTY_NAME", "FWS Linux")),
        ("Build", osr.get("BUILD_ID", "rolling")),
        ("Noyau", _cmd("uname", "-r") or "inconnu"),
        ("Bureau", _desktop()),
        ("Affichage", _session_type()),
        ("Nom de machine", _cmd("hostname") or os.uname().nodename),
        ("Processeur", _cpu()),
        ("Mémoire", _mem()),
        ("Carte(s) graphique(s)", "\n".join(_gpus())),
        ("Disque(s)", "\n".join(_disks())),
    ]
    scroll = Gtk.ScrolledWindow()
    scroll.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC)
    scroll.add(_grid(rows))
    return scroll


class AboutWindow(Gtk.Window):
    def __init__(self):
        super().__init__(title="À propos de FWS")
        self.set_default_size(520, 460)
        self.set_position(Gtk.WindowPosition.CENTER)
        self.set_type_hint(Gdk.WindowTypeHint.DIALOG)

        osr = _osrelease()
        notebook = Gtk.Notebook()
        notebook.append_page(_project_tab(osr), Gtk.Label(label="Le projet FWS"))
        notebook.append_page(_system_tab(osr), Gtk.Label(label="Système"))
        self.add(notebook)
        self.connect("destroy", Gtk.main_quit)


def main():
    if not Gtk.init_check()[0]:
        return 1
    win = AboutWindow()
    win.show_all()
    Gtk.main()
    return 0


if __name__ == "__main__":
    raise SystemExit(main())
