#!/usr/bin/env bash

# List-driven launcher commands, through `vicinae dmenu`.
#
#   panama-pick window        fuzzy-switch to an open window
#   panama-pick quit-window   pick a window; SIGTERM it, SIGKILL on repeat
#   panama-pick process       pick a process by CPU; SIGTERM it
#   panama-pick ssh           pick a Host from ~/.ssh/config; open a session
#   panama-pick recent        pick a recently used file; open it
#   panama-pick password      pick a Bitwarden entry; copy it, concealed
#
# One helper rather than five scripts because every subcommand is the same
# sentence: build a list, let dmenu pick a line, act on the index. dmenu is
# vicinae's own list view, so these read as launcher commands without a
# compiled extension behind them.

set -uo pipefail

# Prints the picked index for the lines on stdin, or nothing on Escape.
menu() {
  vicinae dmenu --navigation-title "$1" --section-title "$2" \
    --format index --no-section 2>/dev/null
}

# Selected line (1-indexed by dmenu's 0-indexed output) from a saved list.
line_at() {
  sed -n "$(( $1 + 1 ))p"
}

case "${1:-}" in
  window|quit-window)
    clients="$(hyprctl clients -j | jq -r '
      [.[] | select(.mapped and .workspace.id > 0)] | sort_by(.workspace.id)[]
      | [.address, .pid, "\(.title)   (\(.class), workspace \(.workspace.id))"]
      | @tsv')"
    [[ -n "$clients" ]] || exit 0
    title="Switch to window"; [[ "$1" == quit-window ]] && title="Force quit window"
    idx="$(cut -f3 <<<"$clients" | menu "$title" 'Windows ({count})')" || exit 0
    [[ -n "$idx" ]] || exit 0
    picked="$(line_at "$idx" <<<"$clients")"
    address="$(cut -f1 <<<"$picked")"
    pid="$(cut -f2 <<<"$picked")"
    if [[ "$1" == window ]]; then
      # The Lua dispatch form. `hyprctl dispatch focuswindow address:0x...`
      # is read as Lua source on 0.56 and fails with a parse error.
      exec hyprctl dispatch "hl.dsp.focus({ window = \"address:$address\" })"
    fi
    # TERM first; the window still being mapped a moment later means the app
    # ignored it, which is what force quit exists for.
    kill "$pid" 2>/dev/null || true
    sleep 1
    if hyprctl clients -j | jq -e --arg a "$address" '.[] | select(.address == $a)' >/dev/null 2>&1; then
      kill -9 "$pid" 2>/dev/null || true
    fi
    ;;
  process)
    procs="$(ps -eo pid=,pcpu=,comm= --sort=-pcpu | awk -v self=$$ '$1 != self { printf "%s\t%5.1f%%  %s\n", $1, $2, $3 }' | head -60)"
    [[ -n "$procs" ]] || exit 0
    idx="$(cut -f2 <<<"$procs" | menu "Kill process" 'By CPU ({count})')" || exit 0
    [[ -n "$idx" ]] || exit 0
    pid="$(line_at "$idx" <<<"$procs" | cut -f1)"
    kill "$pid" 2>/dev/null \
      && notify-send "Sent SIGTERM to $pid" 2>/dev/null || true
    ;;
  ssh)
    config="$HOME/.ssh/config"
    hosts="$( [[ -r "$config" ]] && awk '/^[Hh]ost / { for (i = 2; i <= NF; i++) if ($i !~ /[*?]/) print $i }' "$config" | sort -u )"
    if [[ -z "$hosts" ]]; then
      notify-send "SSH Hosts" "No hosts in ~/.ssh/config" 2>/dev/null || true
      exit 0
    fi
    idx="$(menu "Open SSH session" 'Hosts ({count})' <<<"$hosts")" || exit 0
    [[ -n "$idx" ]] || exit 0
    host="$(line_at "$idx" <<<"$hosts")"
    # kitty, matching hypr/keybinds.lua -- the terminal is written down in a
    # few places and this one keeps the same value until one owner exists.
    exec kitty --detach ssh "$host"
    ;;
  recent)
    xbel="$HOME/.local/share/recently-used.xbel"
    entries="$( [[ -r "$xbel" ]] && python3 - "$xbel" <<'PY'
import sys, urllib.parse, xml.etree.ElementTree as ET
try:
    root = ET.parse(sys.argv[1]).getroot()
except ET.ParseError:
    sys.exit(0)
marks = [(b.get("modified") or "", b.get("href") or "") for b in root.iter("bookmark")]
for _, href in sorted(marks, reverse=True)[:40]:
    if href.startswith("file://"):
        path = urllib.parse.unquote(href[7:])
        print(f"{path}")
PY
    )"
    if [[ -z "$entries" ]]; then
      notify-send "Recent Files" "Nothing recorded yet" 2>/dev/null || true
      exit 0
    fi
    idx="$(sed "s|^$HOME|~|" <<<"$entries" | menu "Open recent file" 'Recent ({count})')" || exit 0
    [[ -n "$idx" ]] || exit 0
    exec xdg-open "$(line_at "$idx" <<<"$entries")"
    ;;
  password)
    # The security shape, in one place:
    #   * the secret travels rbw -> pipe -> wl-copy; it is never an argument
    #     and never a file (argv is world-readable, files outlive intentions)
    #   * --sensitive offers the x-kde-passwordManagerHint MIME, which
    #     vicinae's clipboard history documents it ignores -- verified against
    #     the live history before this was written
    #   * the clipboard clears itself after 30 seconds, from a transient timer
    #     so it happens even if this shell is long gone
    if ! command -v rbw >/dev/null 2>&1; then
      notify-send "Passwords" "rbw is not installed" 2>/dev/null || true
      exit 1
    fi
    if ! entries="$(rbw list --fields name,user 2>/dev/null)" || [[ -z "$entries" ]]; then
      notify-send "Passwords" \
        "rbw is not set up. Run: rbw config set email <you>; rbw register; rbw login" \
        2>/dev/null || true
      exit 0
    fi
    idx="$(awk -F'\t' '{ if ($2 != "") printf "%s   (%s)\n", $1, $2; else print $1 }' <<<"$entries" \
      | menu "Copy password" 'Bitwarden ({count})')" || exit 0
    [[ -n "$idx" ]] || exit 0
    picked="$(line_at "$idx" <<<"$entries")"
    name="$(cut -f1 <<<"$picked")"
    user="$(cut -f2 <<<"$picked")"
    # `--` keeps an entry named like a flag from parsing as one; the pipeline
    # status catches a vault that locked between list and get, so a failed
    # read is reported instead of an empty copy claiming success.
    if ! rbw get -- "$name" ${user:+"$user"} | wl-copy --trim-newline --sensitive; then
      notify-send "Passwords" "Could not read \"$name\" — is the vault locked?" 2>/dev/null || true
      exit 1
    fi
    systemd-run --user --collect --on-active=30s \
      --unit="panama-clip-clear-$(date +%s)-$RANDOM" \
      wl-copy --clear >/dev/null 2>&1 || true
    notify-send --icon=dialog-password-symbolic \
      "Password copied" "\"$name\" — the clipboard clears in 30 seconds" 2>/dev/null || true
    ;;
  *)
    echo 'usage: panama-pick window|quit-window|process|ssh|recent|password' >&2
    exit 2
    ;;
esac
