#!/usr/bin/env bash
set -Eeuo pipefail

# Display Switcher installer (Ubuntu/GNOME ориентировано)
# Делает установку "из коробки": user systemd unit + GNOME shortcut Win+P
# Авторский стиль: без многабукав пользователю, но с нормальной диагностикой.

APP_NAME="display-switcher"
SERVICE_NAME="display-switcher.service"

# ---------- utils ----------
say() { echo -e "$*"; }
die() { echo -e "✗ $*" >&2; exit 1; }

have_cmd() { command -v "$1" >/dev/null 2>&1; }

abs_path() {
  # realpath есть почти всегда, но подстрахуемся
  if have_cmd realpath; then
    realpath "$1"
  else
    python3 - <<'PY' "$1"
import os,sys
print(os.path.abspath(sys.argv[1]))
PY
  fi
}

is_gnome_session() {
  # “точно GNOME” определить сложно, но хотя бы грубо:
  # - gsettings должен работать
  # - обычно есть XDG_CURRENT_DESKTOP=GNOME или "ubuntu:GNOME"
  [[ "${XDG_CURRENT_DESKTOP:-}" == *"GNOME"* ]] || [[ "${XDG_SESSION_DESKTOP:-}" == *"gnome"* ]] || have_cmd gsettings
}

# ---------- find binary ----------
find_binary() {
  # 1) если путь передали аргументом
  if [[ "${1:-}" != "" ]]; then
    local p="$1"
    [[ -f "$p" ]] || die "Указанный файл не найден: $p"
    [[ -x "$p" ]] || die "Файл не исполняемый: $p"
    echo "$(abs_path "$p")"
    return 0
  fi

  # 2) текущая директория
  if [[ -f "./$APP_NAME" && -x "./$APP_NAME" ]]; then
    echo "$(abs_path "./$APP_NAME")"
    return 0
  fi

  # 3) директория скрипта
  local script_dir
  script_dir="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)"
  if [[ -f "$script_dir/$APP_NAME" && -x "$script_dir/$APP_NAME" ]]; then
    echo "$(abs_path "$script_dir/$APP_NAME")"
    return 0
  fi

  # 4) попытка найти в типичных build-папках рядом
  local candidate
  candidate="$(find "$script_dir" -maxdepth 4 -type f -name "$APP_NAME" -perm -111 2>/dev/null | head -n 1 || true)"
  if [[ "$candidate" != "" ]]; then
    echo "$(abs_path "$candidate")"
    return 0
  fi

  die "Не нашёл исполняемый файл '$APP_NAME'.\nЗапусти скрипт из папки где лежит '$APP_NAME' или передай путь:\n  ./install.sh /path/to/$APP_NAME"
}

# ---------- install locations ----------
choose_install_bin() {
  # Без sudo — ставим в ~/.local/bin
  local user_bin="$HOME/.local/bin/$APP_NAME"
  echo "$user_bin"
}

ensure_dirs() {
  mkdir -p "$HOME/.local/bin"
  mkdir -p "$HOME/.config/systemd/user"
  mkdir -p "$HOME/.local/share/applications"
}

binary_supports_toggle() {
  local bin="$1"
  # Не валим установку, если --help не работает
  if "$bin" --help >/dev/null 2>&1; then
    "$bin" --help 2>/dev/null | grep -q -- "--toggle" && return 0
  fi
  return 1
}

# ---------- GNOME settings: disable built-in + add custom shortcut ----------
disable_gnome_switch_monitor() {
  # Отключаем штатный Win+P
  # В разных версиях GNOME ключи могут быть в разных схемах — пробуем оба.
  if have_cmd gsettings; then
    gsettings set org.gnome.mutter.keybindings switch-monitor "[]" >/dev/null 2>&1 || true
    gsettings set org.gnome.settings-daemon.plugins.media-keys switch-monitor "[]" >/dev/null 2>&1 || true
  fi
}

add_custom_shortcut_win_p() {
  local cmd="$1"
  local base="/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings"
  local key="$base/display-switcher/"

  have_cmd gsettings || return 0

  # Добавим путь в массив custom-keybindings (если его там нет)
  local existing
  existing="$(gsettings get org.gnome.settings-daemon.plugins.media-keys custom-keybindings 2>/dev/null || echo "[]")"

  if [[ "$existing" != *"$key"* ]]; then
    local newlist
    if [[ "$existing" == "@as []" || "$existing" == "[]" ]]; then
      newlist="['$key']"
    else
      # аккуратно: подрежем закрывающую скобку и добавим элемент
      # existing обычно выглядит как "['/path1/', '/path2/']"
      newlist="${existing%]*}, '$key']"
      # если вдруг формат странный — откатимся к одиночному списку
      [[ "$newlist" == *"["*"]"* ]] || newlist="['$key']"
    fi
    gsettings set org.gnome.settings-daemon.plugins.media-keys custom-keybindings "$newlist" >/dev/null 2>&1 || true
  fi

  # Настройки самого бинда
  gsettings set org.gnome.settings-daemon.plugins.media-keys.custom-keybinding:"$key" name "Display Switcher" >/dev/null 2>&1 || true
  gsettings set org.gnome.settings-daemon.plugins.media-keys.custom-keybinding:"$key" command "$cmd" >/dev/null 2>&1 || true
  gsettings set org.gnome.settings-daemon.plugins.media-keys.custom-keybinding:"$key" binding "<Super>p" >/dev/null 2>&1 || true
}

# ---------- systemd user unit ----------
write_user_unit() {
  local installed_bin="$1"

  cat > "$HOME/.config/systemd/user/$SERVICE_NAME" <<EOF
[Unit]
Description=Display Switcher (user)
After=graphical-session.target
Wants=graphical-session.target

[Service]
Type=simple
ExecStart=$installed_bin
Restart=on-failure
RestartSec=2

# Важно: это user-unit, так что окружение сессии (DBus/XDG_RUNTIME_DIR/Wayland) будет нормальным.

[Install]
WantedBy=default.target
EOF
}

systemd_user_reload_enable_start() {
  have_cmd systemctl || return 0

  # systemctl --user требует живой пользовательской сессии (обычно есть в обычном терминале под GNOME)
  if ! systemctl --user daemon-reload >/dev/null 2>&1; then
    say "⚠ Не получилось выполнить: systemctl --user daemon-reload"
    say "  Скорее всего, скрипт запущен не в пользовательской графической сессии."
    say "  Установку я всё равно завершил, но сервис нужно включить в обычной сессии GNOME."
    return 0
  fi

  systemctl --user enable --now "$SERVICE_NAME" >/dev/null 2>&1 || true
}

# ---------- desktop entry ----------
write_desktop_entry() {
  local installed_bin="$1"

  cat > "$HOME/.local/share/applications/display-switcher.desktop" <<EOF
[Desktop Entry]
Version=1.0
Type=Application
Name=Display Switcher
Comment=Переключение режимов мониторов (Win+P)
Exec=$installed_bin
Icon=video-display
Terminal=false
Categories=Utility;Settings;
Keywords=display;monitor;screen;projection;
EOF

  # Обновление кеша меню — не обязательно, но приятно
  if have_cmd update-desktop-database; then
    update-desktop-database "$HOME/.local/share/applications" >/dev/null 2>&1 || true
  fi
}

# ---------- main ----------
say "========================================"
say "Display Switcher - Установка"
say "========================================"
say ""

BIN_SRC="$(find_binary "${1:-}")"
say "✓ Найден бинарник:"
say "  $BIN_SRC"
say ""

ensure_dirs

BIN_DST="$(choose_install_bin)"

say "1) Установка бинарника в ~/.local/bin/ ..."
cp -f "$BIN_SRC" "$BIN_DST"
chmod +x "$BIN_DST"
say "✓ Готово: $BIN_DST"
say ""

# Команда для хоткея: желательно --toggle
HOTKEY_CMD="$BIN_DST"
if binary_supports_toggle "$BIN_DST"; then
  HOTKEY_CMD="$BIN_DST --toggle"
fi

say "2) Настройка GNOME (Win+P)..."
if is_gnome_session && have_cmd gsettings; then
  disable_gnome_switch_monitor
  add_custom_shortcut_win_p "$HOTKEY_CMD"
  say "✓ Отключил штатное переключение монитора и назначил Win+P на Display Switcher"
else
  say "⚠ Похоже, это не GNOME-сессия или нет gsettings. Пропускаю настройку Win+P."
fi
say ""

say "3) Создание systemd user-сервиса..."
write_user_unit "$BIN_DST"
systemd_user_reload_enable_start
say "✓ Сервис создан: ~/.config/systemd/user/$SERVICE_NAME"
say ""

say "4) Ярлык в меню приложений..."
write_desktop_entry "$BIN_DST"
say "✓ Ярлык добавлен: ~/.local/share/applications/display-switcher.desktop"
say ""

say "========================================"
say "✓ Установка завершена!"
say "========================================"
say ""
say "Что сделано:"
say "  • Бинарник: $BIN_DST"
say "  • Сервис: systemd --user ($SERVICE_NAME)"
say "  • Горячая клавиша: Win+P (через GNOME Custom Shortcut)"
say "  • Ctrl+P: НЕ используется (это печать)"
say ""

# Попробуем запустить/дернуть сразу, если сервис не стартанул
if have_cmd systemctl; then
  if systemctl --user is-active --quiet "$SERVICE_NAME" 2>/dev/null; then
    say "✓ Сервис уже запущен."
  else
    say "ℹ Если Win+P не сработал сразу: выйди/войдите в сессию GNOME (иногда нужно, чтобы gsettings подхватился)."
    say "  Либо просто запусти программу из меню: Display Switcher."
  fi
fi

say ""
say "Спасибо за использование!"
say "https://madmentat.ru"

