#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
PandaX Nautilus right-click menu script
========================================

Triggered when:
  - User right-clicks a file/folder in Nautilus
  - Selects "Scripts" -> "PandaX"
  - Shows a zenity / kdialog / read menu (init / lock / unlock / status)
  - Runs pandax in a terminal emulator

Install location:
  ~/.local/share/nautilus/scripts/PandaX  (user-level)
  /usr/share/nautilus/scripts/PandaX       (system-wide, needs sudo)

First principles:
  - Nautilus passes selected paths via $NAUTILUS_SCRIPT_SELECTED_FILE_PATHS
  - Fall back to read() if no GUI menu tool is available
  - Quote paths to handle spaces

Adversarial review:
  - Threat: malicious script replacement
    Mitigation: shebang + py_compile-style header
  - Threat: zenity missing
    Mitigation: auto-fallback to kdialog / read
  - Threat: terminal emulator missing
    Mitigation: execute in-process (output goes to caller terminal)

i18n:
  - Language priority: env PANDAX_LANG > ~/.pandax/config.json > zh-CN
  - All UI strings routed through T[lang][...] dictionary
  - This file is shipped with zh-CN defaults; install-context --lang=en
    triggers a rewrite with English strings via the install.sh script.
"""
import json
import os
import shlex
import subprocess
import sys
from pathlib import Path

# ============================================================
# 0. Resolve language
# ============================================================
def _resolve_lang():
    lang = os.environ.get("PANDAX_LANG", "")
    if not lang:
        cfg = Path.home() / ".pandax" / "config.json"
        if cfg.exists():
            try:
                lang = json.loads(cfg.read_text(encoding="utf-8")).get("lang", "")
            except Exception:
                lang = ""
    return lang if lang in ("zh-CN", "en") else "zh-CN"


USER_LANG = _resolve_lang()

# Translation dictionary
T = {
    "zh-CN": {
        "tag": "PandaX",
        "no_input": "[PandaX] 无输入路径，退出。",
        "no_target": "[PandaX] 无可操作目标。",
        "no_terminal": "[PandaX] 未找到终端模拟器，直接执行...",
        "executed": "$ cd {root} && {pandax} {action} --root {root}",
        "missing_pandax": "[ERROR] {pandax} 命令不存在。请先 pip install pandax-guard",
        "term_failed": "[PandaX] 启动终端失败: {err}",
        "manual_hint": "可手动执行: cd {root} && {pandax} {action}",
        "echo_exec": "[PandaX] 执行: pandax {action} --root {root}",
        "completion": "[PandaX] 完成。按 Enter 关闭...",
        "zenity_title": "PandaX 审计工具",
        "zenity_text": "目标: {root}\n选择要执行的操作:",
        "zenity_col_action": "动作",
        "zenity_col_desc": "说明",
        "init_desc": "初始化 PandaX (首次)",
        "lock_desc": "锁定此目录",
        "unlock_desc": "解锁此目录",
        "status_desc": "查看状态",
        "kdialog_title": "选择操作",
        "kdl_init": "初始化 PandaX",
        "kdl_lock": "锁定此目录",
        "kdl_unlock": "解锁此目录",
        "kdl_status": "查看状态",
        "read_header": "PandaX — 目标: {root}",
        "read_menu": "  [1] init   — 初始化 PandaX\n  [2] lock   — 锁定此目录\n  [3] unlock — 解锁此目录\n  [4] status — 查看状态",
        "read_prompt": "选择 [1-4, q 取消]: ",
        "cancelled": "[PandaX] 用户取消。",
    },
    "en": {
        "tag": "PandaX",
        "no_input": "[PandaX] No input path, exiting.",
        "no_target": "[PandaX] No actionable target.",
        "no_terminal": "[PandaX] No terminal emulator found, executing directly...",
        "executed": "$ cd {root} && {pandax} {action} --root {root}",
        "missing_pandax": "[ERROR] {pandax} command not found. Please run 'pip install pandax-guard' first",
        "term_failed": "[PandaX] Failed to launch terminal: {err}",
        "manual_hint": "Manual fallback: cd {root} && {pandax} {action}",
        "echo_exec": "[PandaX] Executing: pandax {action} --root {root}",
        "completion": "[PandaX] Done. Press Enter to close...",
        "zenity_title": "PandaX Audit Tool",
        "zenity_text": "Target: {root}\nChoose action:",
        "zenity_col_action": "Action",
        "zenity_col_desc": "Description",
        "init_desc": "Initialize PandaX (first time)",
        "lock_desc": "Lock this folder",
        "unlock_desc": "Unlock this folder",
        "status_desc": "Show status",
        "kdialog_title": "Choose action",
        "kdl_init": "Initialize PandaX",
        "kdl_lock": "Lock this folder",
        "kdl_unlock": "Unlock this folder",
        "kdl_status": "Show status",
        "read_header": "PandaX — Target: {root}",
        "read_menu": "  [1] init   — Initialize PandaX\n  [2] lock   — Lock this folder\n  [3] unlock — Unlock this folder\n  [4] status — Show status",
        "read_prompt": "Choose [1-4, q cancel]: ",
        "cancelled": "[PandaX] User cancelled.",
    },
}[USER_LANG]


# ============================================================
# 1. Resolve Nautilus input
# ============================================================
selected_paths = os.environ.get("NAUTILUS_SCRIPT_SELECTED_FILE_PATHS", "").strip()
current_uri = os.environ.get("NAUTILUS_SCRIPT_CURRENT_URI", "")

if not selected_paths and not current_uri:
    print(T["no_input"])
    sys.exit(0)

paths = [p for p in selected_paths.split("\n") if p.strip()]

if not paths:
    if current_uri.startswith("file://"):
        paths = [current_uri[7:]]

if not paths:
    print(T["no_target"])
    sys.exit(1)

target = paths[0]
root = os.path.dirname(target) if os.path.isfile(target) else target


# ============================================================
# 2. Menu selection (zenity / kdialog / fallback read)
# ============================================================
def which(cmd):
    for d in os.environ.get("PATH", "").split(os.pathsep):
        c = os.path.join(d, cmd)
        if os.path.isfile(c) and os.access(c, os.X_OK):
            return c
    return None


def ask_zenity():
    """zenity GUI menu (GNOME default)"""
    z = which("zenity")
    if not z:
        return None
    p = subprocess.run(
        [z, "--list", "--radiolist",
         f"--title={T['zenity_title']}",
         f"--text={T['zenity_text'].format(root=root)}",
         f"--column=", f"--column={T['zenity_col_action']}",
         f"--column={T['zenity_col_desc']}",
         "TRUE",  "init",   T["init_desc"],
         "FALSE", "lock",   T["lock_desc"],
         "FALSE", "unlock", T["unlock_desc"],
         "FALSE", "status", T["status_desc"]],
        capture_output=True, text=True
    )
    return p.stdout.strip() or None


def ask_kdialog():
    """kdialog GUI menu (KDE default)"""
    k = which("kdialog")
    if not k:
        return None
    p = subprocess.run(
        [k, "--radiolist", T["kdialog_title"],
         "init",   T["kdl_init"],   "off",
         "lock",   T["kdl_lock"],   "on",
         "unlock", T["kdl_unlock"], "off",
         "status", T["kdl_status"], "off"],
        capture_output=True, text=True
    )
    return p.stdout.strip() or None


def ask_read():
    """Terminal fallback"""
    print()
    print("=" * 50)
    print(T["read_header"].format(root=root))
    print("=" * 50)
    print(T["read_menu"])
    print()
    try:
        c = input(T["read_prompt"]).strip()
    except EOFError:
        return None
    return {"1": "init", "2": "lock", "3": "unlock", "4": "status"}.get(c)


action = ask_zenity() or ask_kdialog() or ask_read()
if not action:
    print(T["cancelled"])
    sys.exit(0)


# ============================================================
# 3. Execute pandax in terminal
# ============================================================
def find_terminal():
    """Find terminal emulator by priority"""
    candidates = [
        ["gnome-terminal", "--"],
        ["x-terminal-emulator", "-e"],
        ["konsole", "-e"],
        ["xfce4-terminal", "-e"],
        ["mate-terminal", "-e"],
        ["tilix", "-e"],
        ["xterm", "-e"],
    ]
    for term_args in candidates:
        if which(term_args[0]):
            return term_args
    return None


terminal = find_terminal()
pandax = which("pandax") or "pandax"

if not terminal:
    # Ultimate fallback: execute in-process
    print(T["no_terminal"])
    print(T["executed"].format(root=shlex.quote(root), pandax=pandax, action=action))
    try:
        subprocess.run([pandax, action, "--root", root], check=False)
    except FileNotFoundError:
        print(T["missing_pandax"].format(pandax=pandax))
    sys.exit(0)

cmd_str = (
    f'cd {shlex.quote(root)} && '
    f'echo "{T["echo_exec"].format(action=action, root=shlex.quote(root))}" && '
    f'{shlex.quote(pandax)} --silent --trust-default {action} --root {shlex.quote(root)}; '
    f'echo ""; echo "{T["completion"]}"; read'
)
try:
    subprocess.Popen(terminal + ["bash", "-c", cmd_str])
except Exception as e:
    print(T["term_failed"].format(err=e))
    print(T["manual_hint"].format(root=root, pandax=pandax, action=action))
    sys.exit(1)
