#!/bin/bash

# omarchy:summary=Pause or resume Hyprland config auto-reload around package transactions.
# omarchy:hidden=true

set -euo pipefail

command="${1:-}"
case "$command" in
  pause | resume | paused) ;;
  *)
    echo "Usage: omarchy-hyprland-reload-guard pause|resume|paused" >&2
    exit 1
    ;;
esac

run_root="${OMARCHY_HYPRLAND_RELOAD_GUARD_RUN_ROOT:-/run/user}"
state_dir="${OMARCHY_HYPRLAND_RELOAD_GUARD_STATE_DIR:-/run/omarchy/hyprland-reload-guard}"
hyprctl_bin="${HYPRCTL:-/usr/bin/hyprctl}"

hyprctl_instance() {
  local runtime_dir="$1"
  local signature="$2"
  shift 2

  XDG_RUNTIME_DIR="$runtime_dir" "$hyprctl_bin" --instance "$signature" "$@"
}

option_bool() {
  local runtime_dir="$1"
  local signature="$2"
  local option="$3"

  # A dead instance makes hyprctl print "Couldn't connect ..." on stdout, so
  # silence jq too and let the failed pipeline skip the instance.
  hyprctl_instance "$runtime_dir" "$signature" -j getoption "$option" 2>/dev/null | jq -r '.bool' 2>/dev/null
}

instances() {
  local instance_dir signature hypr_dir runtime_dir uid

  [[ -d $run_root ]] || return 0

  for instance_dir in "$run_root"/*/hypr/*; do
    [[ -d $instance_dir ]] || continue

    signature="${instance_dir##*/}"
    hypr_dir="${instance_dir%/*}"
    runtime_dir="${hypr_dir%/*}"
    uid="${runtime_dir##*/}"

    [[ $uid =~ ^[0-9]+$ ]] || continue

    printf '%s\t%s\n' "$runtime_dir" "$signature"
  done
}

pause_instance() {
  local runtime_dir="$1"
  local signature="$2"
  local disable_autoreload suppress_errors state_file="$state_dir/$signature"

  mkdir -p "$state_dir"

  if [[ ! -f $state_file ]]; then
    disable_autoreload=$(option_bool "$runtime_dir" "$signature" misc.disable_autoreload) || return 0
    suppress_errors=$(option_bool "$runtime_dir" "$signature" debug.suppress_errors) || return 0
    printf '%s\t%s\t%s\n' "$runtime_dir" "$disable_autoreload" "$suppress_errors" >"$state_file"
  fi

  hyprctl_instance "$runtime_dir" "$signature" eval \
    'hl.config({ misc = { disable_autoreload = true }, debug = { suppress_errors = true } })' \
    >/dev/null 2>&1 || true
}

resume_instance() {
  local state_file="$1"
  local signature="${state_file##*/}"
  local runtime_dir disable_autoreload suppress_errors

  IFS=$'\t' read -r runtime_dir disable_autoreload suppress_errors <"$state_file" || return 0

  if [[ -d $runtime_dir ]]; then
    hyprctl_instance "$runtime_dir" "$signature" eval \
      "hl.config({ debug = { suppress_errors = $suppress_errors } })" \
      >/dev/null 2>&1 || true

    hyprctl_instance "$runtime_dir" "$signature" reload >/dev/null 2>&1 || true

    hyprctl_instance "$runtime_dir" "$signature" eval \
      "hl.config({ misc = { disable_autoreload = $disable_autoreload }, debug = { suppress_errors = $suppress_errors } })" \
      >/dev/null 2>&1 || true
  fi

  rm -f "$state_file"
}

case "$command" in
  paused)
    compgen -G "$state_dir/*" >/dev/null
    ;;
  pause)
    while IFS=$'\t' read -r runtime_dir signature; do
      pause_instance "$runtime_dir" "$signature"
    done < <(instances)
    ;;
  resume)
    [[ -d $state_dir ]] || exit 0
    for state_file in "$state_dir"/*; do
      [[ -f $state_file ]] || continue
      resume_instance "$state_file"
    done
    rmdir "$state_dir" 2>/dev/null || true
    ;;
esac
