#!/bin/bash
#
# 遠端桌面一鍵設定（macOS，被控端）
# 說明：https://oawu.tw/blog/macos/remote-desktop/
#
# 用法：
#   curl -fsSL -o /tmp/remote-desktop-install.sh https://oawu.tw/blog/macos/remote-desktop/files/install.sh
#   bash /tmp/remote-desktop-install.sh
#
# ── 會做的事 ─────────────────────────────────────
#   這支腳本本身不改動系統，只檢查做到哪一步、提示下一步。需要改動系統的步驟
#   都要管理員密碼，交給使用者在終端機 App 執行。
#
#   1. 檢查 /Applications/Jump Desktop Connect.app 是否已安裝（不論用哪種方式裝的都算）
#   2. 下載自動切換服務的三個檔案到 /tmp/remote-desktop/
#        sleep-by-power.sh、tw.oawu.sleep-by-power.plist、install-sleep-by-power.sh
#   3. 檢查插電時的睡眠設定：pmset -g custom 的 AC 區 sleep 0、disksleep 0
#   4. 檢查自動切換服務：/Library/LaunchDaemons/tw.oawu.sleep-by-power.plist 存在，
#      且與 /usr/local/sbin/sleep-by-power.sh 兩個檔案都與下載的版本相同
#   5. 驗證：SleepDisabled 符合目前電源（插電 1、電池 0），服務上次結束代碼是 0
#   6. 列出偵測不到、要自己確認的項目
#
# ── 需要人工的步驟 ───────────────────────────────
#   以下都需要管理員密碼，腳本會印出指令後以結束代碼 2 結束，
#   請使用者在終端機 App 執行，再執行一次本腳本：
#     - 安裝 Jump Desktop Connect：brew install --cask jump-desktop-connect
#     - 睡眠設定：sudo pmset -c sleep 0 displaysleep 10 disksleep 0
#     - 自動切換服務：sudo bash /tmp/remote-desktop/install-sleep-by-power.sh
#
#   以下偵測不到，不會擋住腳本，完成時列在最後提醒：
#     - 登入 Jump 帳號（控制端要登入同一個帳號）
#     - 系統設定 ❯ 隱私權與安全性：「螢幕與系統錄音」「輔助使用」打開 Jump Desktop Connect，
#       只能在機器前面點
#     - 控制端的顯示模式設為 Host Displays，並存好帳號密碼
#
# ── 結束代碼 ─────────────────────────────────────
#   0  完成，驗證全數通過
#   1  失敗（下載失敗、驗證未通過等），訊息會說明原因
#   2  需要人工步驟，完成後重新執行本腳本
#
# ── 可重複執行 ───────────────────────────────────
#   已完成的步驟會略過，重跑是安全的。全部設定好之後再跑，只會做檢查。
#
# ── 其他 ─────────────────────────────────────────
#   服務的檔案從 BASE_URL 下載。測試時可用環境變數指到別處，例如本機的開發伺服器：
#     BASE_URL=http://localhost:4321/blog/macos/remote-desktop/files bash install.sh
#   服務的腳本會複製到 root 擁有的 /usr/local/sbin 再執行，不直接執行 /tmp 底下那份：
#   root 執行的服務若讀的是一般使用者改得到的檔案，任何程式都能藉此取得 root 權限。
#

set -euo pipefail

BASE_URL="${BASE_URL:-https://oawu.tw/blog/macos/remote-desktop/files}"

APP="/Applications/Jump Desktop Connect.app"
WORK_DIR="/tmp/remote-desktop"
LABEL="tw.oawu.sleep-by-power"
PLIST="/Library/LaunchDaemons/$LABEL.plist"
SCRIPT="/usr/local/sbin/sleep-by-power.sh"

# 沒有終端機（例如由其他程式代為執行）時不上色，輸出才不會夾雜控制碼
if [ -t 1 ]; then
  BOLD=$'\033[1m' BLUE=$'\033[1;34m' GREEN=$'\033[32m' GRAY=$'\033[90m' YELLOW=$'\033[33m' RED=$'\033[31m' RESET=$'\033[0m'
else
  BOLD='' BLUE='' GREEN='' GRAY='' YELLOW='' RED='' RESET=''
fi
step() { printf '\n%s==>%s %s%s%s\n' "$BLUE" "$RESET" "$BOLD" "$1" "$RESET"; }
ok()   { printf '    %s✔%s %s\n' "$GREEN" "$RESET" "$1"; }
skip() { printf '    %s- %s%s\n' "$GRAY" "$1" "$RESET"; }
warn() { printf '    %s!%s %s\n' "$YELLOW" "$RESET" "$1"; }
fail() { printf '\n%s✘ %s%s\n' "$RED" "$1" "$RESET" >&2; exit 1; }

# 需要人工處理的步驟：說明要做什麼後以結束代碼 2 結束，做完再重跑。
# 不用 read 等待按鍵，因為由其他程式代為執行時沒有終端機可讀
manual() {
  printf '\n%s需要人工處理：%s\n' "$YELLOW" "$RESET"
  printf '    %s\n' "$@"
  printf '\n完成後重新執行本腳本，已完成的步驟會自動略過。\n'
  exit 2
}

# 從 BASE_URL 下載到 WORK_DIR
fetch() {
  curl -fsSL "$BASE_URL/$1" -o "$WORK_DIR/$1" || fail "下載失敗：$BASE_URL/$1"
}

# 讀 pmset -g custom 裡 AC Power 區的某一項
ac_value() {
  pmset -g custom | awk -v key="$1" '
    /^[A-Za-z].*:$/ { ac = ($0 == "AC Power:") }
    ac && $1 == key  { print $2 }'
}

[ "$(uname)" = "Darwin" ] || fail "此腳本只支援 macOS"

# 1. Jump Desktop Connect
step "安裝 Jump Desktop Connect"
if [ -d "$APP" ]; then
  skip "已安裝"
else
  if command -v brew >/dev/null 2>&1; then
    manual "尚未安裝 Jump Desktop Connect。安裝過程要輸入管理員密碼，請在終端機 App 執行：" \
           "  brew install --cask jump-desktop-connect" \
           "或從官網下載安裝：https://jumpdesktop.com/connect/"
  else
    manual "尚未安裝 Jump Desktop Connect，請從官網下載安裝：https://jumpdesktop.com/connect/"
  fi
fi

# 2. 下載服務的檔案
step "下載自動切換服務的檔案"
mkdir -p "$WORK_DIR" 2>/dev/null && [ -w "$WORK_DIR" ] || fail "無法寫入 ${WORK_DIR}，請確認權限"
for f in sleep-by-power.sh "$LABEL.plist" install-sleep-by-power.sh; do
  fetch "$f"
done
ok "$WORK_DIR"

# 3 與 4 都需要管理員密碼，缺的指令收集起來一次列出
todo=()

# 3. 插電時的睡眠設定
step "睡眠設定（插電時）"
ac_sleep="$(ac_value sleep)"
ac_disk="$(ac_value disksleep)"
if [ "$ac_sleep" = 0 ] && [ "$ac_disk" = 0 ]; then
  skip "sleep 0、disksleep 0"
else
  warn "目前 sleep ${ac_sleep:-?}、disksleep ${ac_disk:-?}（要是 0 與 0）"
  todo+=("  sudo pmset -c sleep 0 displaysleep 10 disksleep 0")
fi

# 4. 自動切換服務
step "自動切換服務"
if [ -f "$PLIST" ] && cmp -s "$WORK_DIR/sleep-by-power.sh" "$SCRIPT" && cmp -s "$WORK_DIR/$LABEL.plist" "$PLIST"; then
  skip "已安裝，且與下載的版本相同"
else
  if [ -f "$PLIST" ]; then warn "已安裝，但與下載的版本不同"; else warn "尚未安裝"; fi
  todo+=("  sudo bash $WORK_DIR/install-sleep-by-power.sh")
fi

if [ "${#todo[@]}" -gt 0 ]; then
  manual "以下指令需要管理員密碼，請在終端機 App 依序執行：" \
         "${todo[@]}" \
         "安裝服務時若跳出「已加入背景項目」，請保持允許" \
         "（系統設定 ❯ 一般 ❯ 登入項目與延伸功能）。"
fi

# 5. 驗證
step "驗證"
if pmset -g ps | head -1 | grep -q "AC Power"; then power="AC"; want=1; else power="電池"; want=0; fi
have="$(pmset -g | awk '/SleepDisabled/{print $2}')"
if [ "$have" = "$want" ]; then
  ok "電源：${power}，SleepDisabled ${have}"
else
  fail "電源：${power}，SleepDisabled ${have:-?}（預期 ${want}）。剛插拔電源的話最多要 15 秒才會切換，稍等再執行一次"
fi
# 沒載入時 launchctl 會以非 0 結束，加上 || true 才不會被 pipefail 直接中止
exit_code="$({ launchctl print "system/$LABEL" 2>/dev/null || true; } | awk -F' = ' '/last exit code/{print $2; exit}')"
case "$exit_code" in
  0) ok "服務上次結束代碼：0" ;;
  "") fail "服務沒有載入，請在終端機 App 執行：sudo bash $WORK_DIR/install-sleep-by-power.sh" ;;
  *) fail "服務上次結束代碼：${exit_code}，紀錄見 /var/log/sleep-by-power.log" ;;
esac

step "完成！"
echo "    以下偵測不到，請自己確認："
echo "    1. Jump Desktop Connect 已登入帳號，控制端要登入同一個帳號"
echo "    2. 系統設定 ❯ 隱私權與安全性：「螢幕與系統錄音」「輔助使用」都打開 Jump Desktop Connect"
echo "       只能在機器前面點，沒開的話連進來是黑畫面或無法操作"
echo "    3. 控制端的顯示模式設為 Host Displays，並在連線設定存好帳號密碼"
