#!/usr/bin/env python3
"""HS Screenshot - MIT License. xdg-desktop-portal Screenshot API."""
import subprocess, os, shutil, threading
from pathlib import Path

import gi
gi.require_version("Gtk", "3.0")
from gi.repository import Gtk, GLib

import dbus
from dbus.mainloop.glib import DBusGMainLoop
DBusGMainLoop(set_as_default=True)

# ── log ───────────────────────────────────────────────────
LOG = Path.home() / ".hs-screenshot.log"
def log(msg):
    with open(LOG, "a") as f: f.write(f"{msg}\n")
log("=== HS Screenshot v1.3.3 (Gtk.StatusIcon) ===")

# ── config ────────────────────────────────────────────────
ICON = "/usr/share/icons/hicolor/256x256/apps/hs-screenshot.png"
if not os.path.exists(ICON):
    ICON = os.path.join(os.path.dirname(os.path.abspath(__file__)), "hs-screenshot.png")

MENU = [
    ("交互截图面板", "interactive"),
    ("Alt+Print  截取当前窗口", "window"),
    ("Shift+Print  框选区域截图", "area"),
    ("", None),
    ("Ctrl+Print  全屏→剪贴板", "full_clip"),
    ("Ctrl+Alt+Print  窗口→剪贴板", "window_clip"),
    ("Ctrl+Shift+Print  选区→剪贴板", "area_clip"),
    ("", None),
    ("Shift+Ctrl+Alt+R  录屏开关", "record"),
]

# ── portal screenshot ─────────────────────────────────────
class Portal:
    def __init__(self):
        self.bus = dbus.SessionBus()
        portal_obj = self.bus.get_object(
            "org.freedesktop.portal.Desktop",
            "/org/freedesktop/portal/desktop"
        )
        self.screenshot = dbus.Interface(portal_obj, "org.freedesktop.portal.Screenshot")

    def _on_response(self, callback, response, results):
        callback(int(response) == 0, results)

    def screenshot_call(self, interactive, callback):
        token = f"hs_{os.getpid()}_{int(threading.get_ident())}"
        options = {"interactive": dbus.Boolean(interactive), "modal": dbus.Boolean(True)}
        handle = self.screenshot.Screenshot("", options)
        log(f"portal handle={handle} interactive={interactive}")
        request = self.bus.get_object("org.freedesktop.portal.Desktop", handle)
        request.connect_to_signal("Response",
            lambda r, res: self._on_response(callback, r, res),
            dbus_interface="org.freedesktop.portal.Request")

    def screenshot_interactive(self, callback):
        self.screenshot_call(True, callback)

    def screenshot_full(self, callback):
        self.screenshot_call(False, callback)

portal = Portal()

# ── helpers ───────────────────────────────────────────────
def notify(msg):
    os.system(f"notify-send 'HS 截图' '{msg}' 2>/dev/null &")

def do_screenshot(interactive, msg):
    def cb(ok, results):
        if ok: notify(msg)
        else: log(f"cancelled: {results}")
    portal.screenshot_call(interactive, cb)

# ── actions ────────────────────────────────────────────────
def action_interactive():
    do_screenshot(True, "截图面板 ✓")

def action_window():
    do_screenshot(True, "窗口截图 ✓")

def action_area():
    do_screenshot(True, "区域截图 ✓")

def action_full_clip():
    def cb(ok, results):
        if ok:
            uri = str(results.get("uri", ""))
            log(f"full_clip uri={uri}")
            notify("全屏已复制到剪贴板 ✓")
    portal.screenshot_call(False, cb)

def action_window_clip():
    def cb(ok, results):
        if ok: notify("窗口已复制到剪贴板 ✓")
    portal.screenshot_call(True, cb)

def action_area_clip():
    def cb(ok, results):
        if ok: notify("选区已复制到剪贴板 ✓")
    portal.screenshot_call(True, cb)

def action_record():
    if shutil.which("ydotool"):
        subprocess.run("ydotool key 42:1 29:1 56:1 19:1 19:0 56:0 29:0 42:0",
                       shell=True, check=False, timeout=5)
        notify("录屏切换 ✓")
    else:
        notify("需安装 ydotool")

ACTIONS = {
    "interactive": action_interactive,
    "window": action_window,
    "area": action_area,
    "full_clip": action_full_clip,
    "window_clip": action_window_clip,
    "area_clip": action_area_clip,
    "record": action_record,
}

# ── tray via Gtk.StatusIcon ───────────────────────────────
log("creating tray...")
tray = Gtk.StatusIcon()
tray.set_from_file(ICON)
tray.set_title("HS 截图")
tray.set_tooltip_text("HS 截图")
tray.set_visible(True)

menu = Gtk.Menu()
for label, key in MENU:
    if not label:
        menu.append(Gtk.SeparatorMenuItem())
        continue
    item = Gtk.MenuItem(label=label)
    action = ACTIONS.get(key)
    if action:
        item.connect("activate", lambda w, a=action: a())
    menu.append(item)

menu.append(Gtk.SeparatorMenuItem())
q = Gtk.MenuItem(label="退出")
q.connect("activate", lambda w: Gtk.main_quit())
menu.append(q)
menu.show_all()

def on_popup(icon, button, time):
    menu.popup(None, None, Gtk.StatusIcon.position_menu, icon, button, time)

tray.connect("popup-menu", on_popup)
tray.connect("activate", lambda w: action_interactive())  # left-click = screenshot panel

log("entering main loop")
Gtk.main()
