#!/usr/bin/env bash
# The coordinators' side of the INBOX (inbox.html; the store lives on the VM, see _tools/inbox_server.py).
# Two coordinators share it: --to kills (kills, builds, engine, the game app; the default) and --to live (online, shop,
# seasons, saves, accounts). The live coordinator passes --to live on every call (or exports INBOX_AS=live).
#   bash _tools/inbox.sh pull [--to kills|live]               the user's NEW messages for you as JSON, marked seen by you
#   bash _tools/inbox.sh reply ID "text" [--to kills|live]    reply under message ID (text may also come on stdin)
#   bash _tools/inbox.sh status "text" [--to kills|live]      your short "now" line on top of the page
#   bash _tools/inbox.sh ask --to kills|live --topic "T" "question" [--choices "A|B|C"]   a question for the user
#   bash _tools/inbox.sh ask ... --choices "A|B|C" --multi    the user may tick SEVERAL choices (answers: a JSON list)
#   bash _tools/inbox.sh post --to kills|live --topic "T" "text"   a note/update for the user (no answer needed)
#   bash _tools/inbox.sh answers [--to kills|live]            the user's answers to your questions since the last call
#   bash _tools/inbox.sh unask ID                             withdraw an open question
#   bash _tools/inbox.sh topics | list                        the topics / everything, as JSON
#   bash _tools/inbox.sh deploy                               copy inbox_server.py + inbox_push.py to the VM (backup first) + restart
#   bash _tools/inbox.sh push-status | push-test              phone notifications: devices, queue, last push / a test push now
# A topic is matched by id or title and created when new. Replies may carry links; image URLs under
# https://bashatest.howincloud.com/ (png/jpg/gif/webp) show as pictures on the page.
set -uo pipefail
VM=root@bashatest.howincloud.com
SRV=/srv/stickbash-inbox/server.py
# INBOX_TEST_DIR=/tmp/x points the remote calls at a scratch store on the VM (tests); never set it for real use
[[ -n ${INBOX_TEST_DIR:-} ]] && SRV="/srv/stickbash-inbox/server.py" && PRE="INBOX_DIR=$INBOX_TEST_DIR " || PRE=""
# INBOX_LOCAL_DIR=/tmp/y runs this checkout's inbox_server.py on this machine against a scratch store (tests only)
[[ -n ${INBOX_LOCAL_DIR:-} ]] && SRV="$(cd "$(dirname "$0")" && pwd)/inbox_server.py" && PRE="INBOX_DIR=$INBOX_LOCAL_DIR "
ssh_vm() { local c=$1; shift; if [[ -n ${INBOX_LOCAL_DIR:-} ]]; then bash -c "$PRE$c"; return; fi
  perl -e 'alarm 60; exec @ARGV' ssh -o BatchMode=yes -o ConnectTimeout=15 "$VM" "$PRE$c" "$@"; }
usage() { sed -n '2,17p' "$0" | sed 's/^# \{0,1\}//' >&2; exit 2; }

cmd=${1:-list}; [[ $# -gt 0 ]] && shift
lane=${INBOX_AS:-kills}; topic=""; choices=""; multi=""; pos=()
while [[ $# -gt 0 ]]; do
  case $1 in
    --to|--as) lane=${2:?--to needs kills or live}; shift 2 ;;
    --topic) topic=${2?--topic needs a title}; shift 2 ;;
    --choices) choices=${2?--choices needs "A|B|C"}; shift 2 ;;
    --multi) multi=1; shift ;;
    *) pos+=("$1"); shift ;;
  esac
done
[[ $lane == kills || $lane == live ]] || { echo "inbox: --to must be kills or live" >&2; exit 2; }

case $cmd in
  pull|answers) ssh_vm "python3 $SRV $cmd --to $lane" ;;
  list|topics|push-status|push-test|push-init) ssh_vm "python3 $SRV $cmd" ;;
  reply)
    id=${pos[0]:-}; [[ $id =~ ^[0-9]+$ ]] || { echo 'usage: inbox.sh reply ID "text" [--to kills|live]' >&2; exit 2; }
    if [[ ${#pos[@]} -ge 2 ]]; then printf '%s' "${pos[1]}" | ssh_vm "python3 $SRV reply $id --to $lane"; else ssh_vm "python3 $SRV reply $id --to $lane"; fi ;;
  status)
    if [[ ${#pos[@]} -ge 1 ]]; then printf '%s' "${pos[0]}" | ssh_vm "python3 $SRV status --to $lane"; else ssh_vm "python3 $SRV status --to $lane"; fi ;;
  ask|post)
    text=${pos[0]:-}; [[ -n $text ]] || text=$(cat)
    [[ -n $text ]] || { echo "inbox: $cmd needs the text" >&2; exit 2; }
    [[ -n $multi && $cmd != ask ]] && { echo "inbox: --multi is for ask" >&2; exit 2; }
    TO=$lane TOPIC=$topic CHOICES=$choices TEXT=$text MULTI=$multi python3 -c '
import json, os
c = [x.strip() for x in os.environ["CHOICES"].split("|") if x.strip()]
b = {"to": os.environ["TO"], "topic": os.environ["TOPIC"] or "general", "text": os.environ["TEXT"], "choices": c}
if os.environ["MULTI"]: b["multi"] = True
print(json.dumps(b))' |
      ssh_vm "python3 $SRV $cmd" ;;
  unask)
    id=${pos[0]:-}; [[ $id =~ ^[0-9]+$ ]] || { echo "usage: inbox.sh unask ID" >&2; exit 2; }
    ssh_vm "python3 $SRV unask $id" ;;
  deploy)
    dir=$(cd "$(dirname "$0")" && pwd)
    python3 -m py_compile "$dir/inbox_server.py" "$dir/inbox_push.py" || exit 1
    perl -e 'alarm 60; exec @ARGV' scp -o BatchMode=yes -q "$dir/inbox_server.py" "$VM:/tmp/inbox_server.py" &&
      perl -e 'alarm 60; exec @ARGV' scp -o BatchMode=yes -q "$dir/inbox_push.py" "$VM:/tmp/inbox_push.py" &&
      ssh_vm "t=\$(date +%Y%m%d-%H%M%S); P=/srv/stickbash-inbox/inbox_push.py; cp -p $SRV $SRV.bak-\$t; [ -f \$P ] && cp -p \$P \$P.bak-\$t;
              cp -p /srv/stickbash-inbox/data.json /srv/stickbash-inbox/data.json.bak-\$t 2>/dev/null;
              [ -f /srv/stickbash-inbox/push.json ] && cp -p /srv/stickbash-inbox/push.json /srv/stickbash-inbox/push.json.bak-\$t;
              python3 -m py_compile /tmp/inbox_server.py /tmp/inbox_push.py && install -m 644 /tmp/inbox_push.py \$P &&
              install -m 755 /tmp/inbox_server.py $SRV && systemctl restart stickbash-inbox && sleep 1 && systemctl is-active stickbash-inbox" ;;
  -h|--help|help) usage ;;
  *) usage ;;
esac
