#!/usr/bin/env bash
export LC_ALL=C.UTF-8 2>/dev/null || true
shopt -s extglob
[ -t 1 ] || { echo "Run this in a real terminal"; exit 1; }

rgb() { printf '\e[38;2;%s;%s;%sm' "$1" "$2" "$3"; }
N=$'\e[0m'; B=$'\e[1m'
RED=$(rgb 255 60 80);  ACC=$(rgb 255 115 135); WHT=$(rgb 236 236 246)
GRN=$(rgb 80 250 150); DIM=$(rgb 125 125 145); YEL=$(rgb 255 190 80)
SEL=$'\e[48;2;190;24;52m\e[1;38;2;255;255;255m'

grad() {
  local s=$1 n=${#1} i r g b c out=""
  for ((i = 0; i < n; i++)); do
    r=$(($2 + ($5 - $2) * i / (n > 1 ? n - 1 : 1)))
    g=$(($3 + ($6 - $3) * i / (n > 1 ? n - 1 : 1)))
    b=$(($4 + ($7 - $4) * i / (n > 1 ? n - 1 : 1)))
    printf -v c '\e[38;2;%d;%d;%dm' "$r" "$g" "$b"
    out+="$c${s:i:1}"
  done
  printf '%s%s' "$B$out" "$N"
}

LB=("Install / Reinstall" "Links" "Certificate" "Remote Proxy"
    "Status" "Speed test" "Restart services" "Update"
    "VLESS" "VLESS none-TLS" "VMess" "Trojan"
    "Shadowsocks" "SSH-WebSocket" "Security audit" "Exit")
DS=("Fresh install or repair of every component"
    "Show connection links and QR for all users"
    "Issue or renew the TLS certificate"
    "Set the upstream / remote proxy host"
    "Live health of every service"
    "Measure bandwidth and latency"
    "Restart Nginx, Xray and SSH-WS"
    "Update the script to the latest version"
    "VLESS over WebSocket + TLS"
    "VLESS over WebSocket, plain port 80"
    "VMess over WebSocket"
    "Trojan over TLS"
    "Shadowsocks AEAD"
    "SSH tunnel over WebSocket"
    "Scan config for weak settings"
    "Leave the menu")

W=62; SELI=0; BUF=""; M=0
printf -v HL '%*s' "$W" ''; HL=${HL// /─}

strip() { local s=$1; s=${s//$'\e'\[*([0-9;])m/}; REPLY=${#s}; }
out()   { printf '%*s%s%s\e[K\n' "$M" '' "$1" "$N"; }
row()   { strip "$1"; local p=$((W - REPLY)); ((p < 0)) && p=0
          printf -v SP '%*s' "$p" ''; out "${RED}│${N}$1${N}${SP}${RED}│"; }
crow()  { strip "$1"; local l=$(((W - REPLY) / 2)); printf -v CP '%*s' "$l" ''; row "$CP$1"; }

TITLE=$(grad "C R I M S O N   G A T E" 255 70 90 255 175 60)

chip() {
  local c=$GRN
  if command -v systemctl >/dev/null 2>&1 && systemctl cat "$2" >/dev/null 2>&1; then
    systemctl is-active --quiet "$2" 2>/dev/null || c=$RED
  fi
  STATUS+=" ${c}●${N} ${WHT}$1${N}   "
}
refresh() {
  IP=$(hostname -I 2>/dev/null | awk '{print $1}'); IP=${IP:-n/a}
  RAMV=$(free -m 2>/dev/null | awk '/^Mem:/{printf "%dM / %dM",$3,$2}'); RAMV=${RAMV:-n/a}
  UPV=$(uptime -p 2>/dev/null | sed 's/^up //'); UPV=${UPV:-n/a}
  STATUS=""
  chip "Nginx" nginx; chip "Xray" xray; chip "SSH-WS" crimson-ssh-ws
  STATUS+=" ${GRN}●${N} ${WHT}Cert${N}"
}

cell() {
  local i=$1 num mark=" " plain pad nn
  ((i == 15)) && num=0 || num=$((i + 1))
  ((i == SELI)) && mark="▸"
  printf -v plain ' %s %2s  %s' "$mark" "$num" "${LB[i]}"
  printf -v pad '%*s' $((30 - ${#plain})) ''
  if ((i == SELI)); then
    CELL="${SEL}${plain}${pad}${N}"
  else
    printf -v nn '%2s' "$num"
    CELL=" ${mark} ${ACC}${nn}${N}  ${WHT}${LB[i]}${N}${pad}"
  fi
}

draw() {
  local r a b
  printf '\e[H'
  out "${RED}┌${HL}┐"
  row ""
  crow "$TITLE"
  crow "${DIM}secure tunnel manager  ·  aurora ui${N}"
  row ""
  out "${RED}├${HL}┤"
  row " ${ACC}${IP}${N}  ${DIM}│${N}  ${WHT}RAM ${RAMV}${N}  ${DIM}│  ${UPV}${N}"
  row "$STATUS"
  out "${RED}├${HL}┤"
  row " ${ACC}${B}   MANAGE${N}                        ${ACC}${B}   PROTOCOLS${N}"
  for ((r = 0; r < 8; r++)); do
    cell "$r";        a=$CELL
    cell $((r + 8));  b=$CELL
    row " ${a}${b} "
  done
  out "${RED}├${HL}┤"
  row " ${YEL}▸${N} ${WHT}${DS[SELI]}${N}"
  out "${RED}└${HL}┘"
  out " ${DIM}↑↓←→ move   ⏎ select   type number to jump   r refresh   q quit${N}"
  out " ${ACC}›${N} ${WHT}${BUF}${N}${DIM}_${N}"
  printf '\e[J'
}

act() {
  local i=$1 p f bar rest
  ((i == 15)) && exit 0
  printf '\e[H\e[J'
  out "${RED}┌${HL}┐"
  row ""
  crow "${B}${WHT}${LB[i]}${N}"
  row ""
  out "${RED}└${HL}┘"
  out ""
  for ((p = 0; p <= 100; p += 4)); do
    f=$((p * 40 / 100))
    printf -v bar '%*s' "$f" '';         bar=${bar// /█}
    printf -v rest '%*s' $((40 - f)) ''; rest=${rest// /░}
    printf '\r%*s  %s%s%s%s%s %3d%%' "$M" '' "$RED" "$bar" "$DIM" "$rest" "$N" "$p"
    sleep 0.025
  done
  printf '\n\n'
  if declare -F "action_$i" >/dev/null; then
    "action_$i"
  else
    out "  ${GRN}✔${N} ${WHT}${LB[i]}${N} ${DIM}— demo mode${N}"
  fi
  out ""
  out "  ${DIM}press any key to go back${N}"
  read -rsn1
  printf '\e[H\e[J'
}

up()    { SELI=$(((SELI + 15) % 16)); }
down()  { SELI=$(((SELI + 1) % 16)); }
left()  { ((SELI >= 8)) && SELI=$((SELI - 8)); }
right() { ((SELI < 8)) && SELI=$((SELI + 8)); }
jump() {
  local n
  [[ $BUF == +([0-9]) ]] || return
  n=$((10#$BUF))
  if ((n == 0)); then SELI=15
  elif ((n >= 1 && n <= 15)); then SELI=$((n - 1))
  else BUF=${BUF: -1}; jump; fi
}

resize() { local c; c=$(tput cols 2>/dev/null || echo 80); M=$(((c - W - 2) / 2)); ((M < 0)) && M=0; printf '\e[H\e[J'; }
cleanup() { printf '\e[?25h\e[?1049l%s' "$N"; }
trap cleanup EXIT
trap 'exit 130' INT TERM
trap resize WINCH

printf '\e[?1049h\e[?25l'
refresh; resize

while :; do
  draw
  IFS= read -rsn1 k || break
  if [[ $k == $'\e' ]]; then
    read -rsn2 -t 0.02 k2
    case $k2 in
      '[A') up ;; '[B') down ;; '[C') right ;; '[D') left ;;
    esac
    BUF=""
  elif [[ -z $k ]]; then
    act "$SELI"; BUF=""
  else
    case $k in
      [0-9]) BUF+=$k; jump ;;
      k) up; BUF="" ;; j) down; BUF="" ;; h) left; BUF="" ;; l) right; BUF="" ;;
      r|R) refresh; BUF="" ;;
      q|Q) exit 0 ;;
      $'\x7f') BUF="" ;;
    esac
  fi
done
