#!/usr/bin/env bash
# wormhole installer — generated by https://wormhole.ajxchapman.com
#
#   curl -fsS https://wormhole.ajxchapman.com | bash                  install the 'wormhole' function
#   curl -fsS https://wormhole.ajxchapman.com | bash -s -- --help     every option
#
# Installing writes a marked block into your shell rc file. Re-running replaces
# that block instead of appending another copy, so it is safe to repeat.
set -euo pipefail

BASE="https://wormhole.ajxchapman.com"
BEGIN_MARK='# >>> wormhole >>>'
END_MARK='# <<< wormhole <<<'

snippet() { cat <<'WORMHOLE_SNIPPET_EOF'
# >>> wormhole >>>
# wormhole — ephemeral pipe relay (https://wormhole.ajxchapman.com)
#   wormhole ./dir          send a directory (encrypted, one-shot)
#   wormhole --sync ./dir   only newer/missing files travel
#   wormhole --help         every flag
# Update:  curl -fsS https://wormhole.ajxchapman.com | bash
# Remove:  curl -fsS https://wormhole.ajxchapman.com | bash -s -- --uninstall
wormhole() { curl -fsS "https://wormhole.ajxchapman.com/send" | bash -s -- "$@"; }
# <<< wormhole <<<
WORMHOLE_SNIPPET_EOF
}

show_help() { cat >&2 <<HELPEOF
Usage: curl -fsS $BASE | bash [-s -- OPTIONS]

Install a 'wormhole' shell function that sends a directory through the relay
at $BASE. The function is written into your shell rc file between marker
lines, so re-running this replaces it rather than appending a second copy.

Options:
  (none)            Install into the detected rc file
  --print           Print the block to stdout and exit, changing nothing.
                    For the current shell only:
                      eval "\$(curl -fsS $BASE | bash -s -- --print)"
  --uninstall       Remove the block from the rc file
  --rc FILE         Install into FILE instead of the detected rc
                    (also settable as WORMHOLE_RC=FILE)
  --dry-run         Show what would be written, change nothing
  -h, --help        This help

Once installed:
  wormhole ./dir            send a directory (encrypted, one-shot)
  wormhole --sync ./dir     rsync-style: only newer/missing files travel
  wormhole --plain ./dir    don't encrypt (the relay sees content)
  wormhole --help           every sender flag

Receiving needs no install — the sender prints the exact command to paste,
with the channel id, the mode flags and the secret already in it.

Relay usage without installing anything:
  curl -fsS $BASE/help | less
HELPEOF
}

MODE=install
RC="${WORMHOLE_RC:-}"
DRY=0

while [ $# -gt 0 ]; do
  case "$1" in
    -h|--help)   show_help; exit 0 ;;
    --print)     MODE=print; shift ;;
    --uninstall) MODE=uninstall; shift ;;
    --dry-run)   DRY=1; shift ;;
    --rc)        RC="${2:-}"; [ -n "$RC" ] || { echo "--rc needs a file" >&2; exit 1; }; shift 2 ;;
    *)           echo "unknown option: $1 (try --help)" >&2; exit 1 ;;
  esac
done

command -v curl >/dev/null || { echo "curl required" >&2; exit 1; }

# --print: the block on stdout, everything else on stderr, so
# eval "$(curl -fsS URL | bash -s -- --print)" installs into the current shell.
if [ "$MODE" = "print" ]; then
  echo "# Install into the current shell with:" >&2
  echo "#   eval \"\$(curl -fsS $BASE | bash -s -- --print)\"" >&2
  snippet
  exit 0
fi

# Which rc file: an explicit choice, else the one this user's shell reads.
detect_rc() {
  if [ -n "$RC" ]; then printf '%s\n' "$RC"; return; fi
  case "${SHELL:-}" in
    */zsh) printf '%s\n' "${ZDOTDIR:-$HOME}/.zshrc"; return ;;
  esac
  # macOS bash reads .bash_profile for login shells and traditionally has no
  # .bashrc; everywhere else .bashrc is the right file.
  if [ "$(uname -s 2>/dev/null || echo)" = "Darwin" ] \
     && [ -f "$HOME/.bash_profile" ] && [ ! -f "$HOME/.bashrc" ]; then
    printf '%s\n' "$HOME/.bash_profile"; return
  fi
  printf '%s\n' "$HOME/.bashrc"
}

RC_FILE="$(detect_rc)"

# The block currently in the file, if any (empty when not installed).
current_block() {
  [ -f "$RC_FILE" ] || return 0
  awk -v b="$BEGIN_MARK" -v e="$END_MARK" '
    $0 == b { inb = 1 }
    inb == 1 { print }
    $0 == e { inb = 0 }
  ' "$RC_FILE"
}

# The file with our block removed — both the marked block and the unmarked
# 'alias wormhole=...' line older versions of this tool appended. Leaving that
# alias behind would shadow the function, since an alias wins at parse time.
without_block() {
  [ -f "$RC_FILE" ] || return 0
  awk -v b="$BEGIN_MARK" -v e="$END_MARK" '
    $0 == b { skip = 1; next }
    skip == 1 { if ($0 == e) skip = 0; next }
    /^alias wormhole='"'"'curl -fsS .*\/send [|] bash -s --'"'"'$/ { next }
    /^# wormhole — generated by / { next }
    { print }
  ' "$RC_FILE"
}

had_legacy_alias() {
  [ -f "$RC_FILE" ] || return 1
  grep -qE "^alias wormhole='curl -fsS .*/send [|] bash -s --'$" "$RC_FILE"
}

# Drop trailing blank lines. Applied to the kept part of the file before the
# block is appended, so re-installing doesn't add a blank line every time.
trim_trailing() {
  awk '{ lines[NR] = $0 } END {
    last = NR
    while (last > 0 && lines[last] ~ /^[[:space:]]*$/) last--
    for (i = 1; i <= last; i++) print lines[i]
  }'
}

# Rewrite RC_FILE from stdin. Buffered through a temp file because the stdin
# pipeline is still reading RC_FILE, then written through the existing path
# (rather than mv'ing over it) so its inode, permissions and symlink survive.
rewrite_rc() {
  local tmp
  tmp="$(mktemp)" || { echo "could not create a temp file" >&2; exit 1; }
  trim_trailing > "$tmp"
  cat "$tmp" > "$RC_FILE"
  rm -f "$tmp"
}

if [ "$MODE" = "uninstall" ]; then
  if [ ! -f "$RC_FILE" ]; then
    echo "Nothing to remove: $RC_FILE does not exist." >&2
    exit 0
  fi
  if [ -z "$(current_block)" ] && ! had_legacy_alias; then
    echo "Nothing to remove: no wormhole block in $RC_FILE." >&2
    exit 0
  fi
  if [ "$DRY" = "1" ]; then
    echo "Would remove the wormhole block from $RC_FILE." >&2
    exit 0
  fi
  without_block | rewrite_rc
  echo "Removed the wormhole block from $RC_FILE." >&2
  echo "The function stays defined in shells that already sourced it; 'unset -f wormhole' clears it." >&2
  exit 0
fi

# --- install ---------------------------------------------------------------

DESIRED="$(snippet)"

if [ "$DRY" = "1" ]; then
  echo "Would write into $RC_FILE:" >&2
  echo "" >&2
  snippet >&2
  exit 0
fi

if [ "$(current_block)" = "$DESIRED" ] && ! had_legacy_alias; then
  echo "wormhole is already installed in $RC_FILE (unchanged)." >&2
  exit 0
fi

ACTION="Installed"
[ -z "$(current_block)" ] || ACTION="Updated"
LEGACY=0
had_legacy_alias && LEGACY=1

mkdir -p "$(dirname "$RC_FILE")"
{
  without_block | trim_trailing
  echo ""
  snippet
} | rewrite_rc

{
  echo ""
  echo "  ✓ $ACTION the 'wormhole' function in $RC_FILE"
  if [ "$LEGACY" = "1" ]; then
    echo "    (removed the older 'alias wormhole=...' line it replaces)"
  fi
  echo ""
  echo "  Open a new shell, or:  source $RC_FILE"
  echo ""
  echo "  wormhole ./dir            send a directory (encrypted, one-shot)"
  echo "  wormhole --sync ./dir     only newer/missing files travel"
  echo "  wormhole --help           every flag"
  echo ""
  echo "  The receiver pastes the command your send prints — nothing to install there."
  echo ""
} >&2
