#!/usr/bin/env bash
# OPEN MY WALLET — the whole front door for somebody who owns a wallet and nothing else.
#
# WHY THIS EXISTS (2026-10-02, Vincent): the folder had exactly one entry point, `listen init`,
# and it makes you a STATION. A member who owns one Heltec and no bookkeeper had no mode at all. But
# wallet.html already handles him: "no listener (someone else's laptop, no laptop at all) nothing
# changes: we talk to the board over USB" (wallet.html:556). It drives the board over WebSerial
# and needs no daemon, no station and no sixteen words.
#
# The ONLY thing it needed was to be SERVED instead of double-clicked. A file:// page does not get
# a usable origin, so Chrome will not give it a serial port and the permission never sticks.
# http://127.0.0.1 IS a secure context, so a plain static server is enough.
#
# No install. No dependencies beyond what macOS and Linux already ship.
set -u
HERE="$(cd "$(dirname "$0")" && pwd)"
PAGE="wallet.html"
[ -f "$HERE/$PAGE" ] || { echo "  $PAGE is not next to this script. Nothing to serve."; exit 1; }

# ---------------------------------------------------------------- ONE PORT, ALWAYS. NEVER ROAM.
# ⭐ THIS USED TO HUNT FOR A FREE PORT (8790, then 8791, then 8792...) and that quietly broke the
# one promise the page makes. A WebSerial permission belongs to an ORIGIN, and an origin is
# scheme + host + PORT. So http://127.0.0.1:8790 and http://127.0.0.1:8791 are two different
# websites to Chrome. Move the port and the browser has never heard of your wallet: getPorts()
# comes back empty, the page waits, and it never even asks -- because it only asks when you press
# the button. Meanwhile it is still telling you "it only asks once, after that this page reconnects
# on its own", which has just become false for a reason nobody could possibly guess.
#
# Found 2026-10-08 with two folders open: 8790 held the old one, the new one took 8791, and the
# board went invisible. A roaming port is fine for a plain static server. It is not fine when the
# port IS the key to your hardware permission.
#
# So: one port, forever. If it is busy, find out WHY instead of fleeing.
port=8790
busy() { (exec 3<>"/dev/tcp/127.0.0.1/$1") 2>/dev/null && { exec 3>&-; return 0; } || return 1; }
URL="http://127.0.0.1:$port/$PAGE"

# Is the thing on our port already OUR wallet? Then there is nothing to start: open the browser at
# it and let the permission the keeper already granted keep working.
ours() { curl -fsS --max-time 2 "$URL" 2>/dev/null | grep -q "the Sounding Society"; }

# ---------------------------------------------------------------- the browser
# WEBSERIAL IS CHROME AND EDGE ONLY. Safari and Firefox do not implement it at all, and
# wallet.html:1181 fails SILENTLY there -- a page that does nothing and says nothing, which for a
# stranger is the worst possible version. So we pick a browser that works, and if there is none we
# say so in words instead of opening one that cannot.
open_in_a_browser_that_works() {
  case "$(uname)" in
    Darwin)
      for app in "Google Chrome" "Microsoft Edge" "Brave Browser" "Chromium"; do
        if [ -d "/Applications/$app.app" ]; then open -a "$app" "$URL"; echo "  opened $app"; return 0; fi
      done ;;
    *)
      for b in google-chrome google-chrome-stable chromium chromium-browser microsoft-edge brave-browser; do
        if command -v "$b" >/dev/null 2>&1; then "$b" "$URL" >/dev/null 2>&1 & echo "  opened $b"; return 0; fi
      done ;;
  esac
  echo
  echo "  I could not find Chrome, Edge, Brave or Chromium on this computer."
  echo "  Your wallet page needs one of them: it talks to your board through the browser,"
  echo "  and Safari and Firefox cannot do that at all -- on those the page just sits there"
  echo "  looking fine and doing nothing."
  echo
  echo "  Install Chrome, then open this address yourself:"
  echo "      $URL"
  return 1
}

# ---------------------------------------------------------------- serve it
serve() {
  if command -v python3 >/dev/null 2>&1 && python3 -c "" >/dev/null 2>&1; then
    exec python3 -m http.server "$port" --bind 127.0.0.1 --directory "$HERE" >/dev/null 2>&1
  elif command -v ruby >/dev/null 2>&1; then
    exec ruby -run -e httpd -- "$HERE" -p "$port" -b 127.0.0.1 >/dev/null 2>&1   # macOS still ships ruby; no install needed
  else
    echo "  This needs python3 or ruby to serve the page, and neither is here." >&2
    exit 1
  fi
}

if busy "$port"; then
  if ours; then
    echo
    echo "  Your wallet is already open at $URL"
    echo "  (Opening it again here rather than on a new address, because moving"
    echo "   addresses is what makes the browser forget your board.)"
    echo
    open_in_a_browser_that_works
    exit 0
  fi
  echo
  echo "  Something else on this computer is already using port $port, and it is not your wallet."
  echo
  echo "  Your wallet has to use this one address every time. The browser ties its"
  echo "  permission to see your board to the exact address, so if we moved to another"
  echo "  port the page would open, find nothing, and never tell you why."
  echo
  echo "  Close whatever is on $port and double-click this again."
  echo
  exit 1
fi

cat <<BANNER

  SOUNDING SOCIETY -- your wallet

  Plug your wallet into this computer with a USB cable that carries DATA.
  (A charge-only cable lights the board up and is invisible to the computer.
   A blue USB-3 cable always carries data.)

  Serving on $URL

  In the page, press CONNECT and pick your board from the list the browser
  shows you. The browser asks once, on purpose -- a web page is never allowed
  to go looking through your ports by itself. After that it reconnects on its
  own every time.

  You do NOT need a bookkeeper, a station, or your sixteen words for this.
  Your balance is on the board and the page reads it straight off.

  Leave this window open while you use the wallet.  Ctrl-C when you are done.

BANNER
serve & SRV=$!
trap 'kill $SRV 2>/dev/null' EXIT INT TERM
for _ in 1 2 3 4 5 6 7 8 9 10; do busy "$port" && break; sleep 0.2; done
busy "$port" || { echo "  the server did not come up on $port"; exit 1; }
open_in_a_browser_that_works
wait $SRV
