#!/bin/sh
# Install the nyx CLI — the icosahedra.com image tools, without a browser.
#
#   curl -fsSL https://icosahedra.com/cli/install.sh -o install.sh
#   sh install.sh [target-dir]            # default: ./nyx
#
# It fetches https://icosahedra.com/cli/manifest.txt and the ~37 files it
# lists (about 1 MB, mostly wasm), mirroring the site's paths. There is no
# build step and no package manager: the site serves the source as-is, so an
# install is a copy.
#
#   --from <base-url>   install from somewhere else (a local ./serve.sh, say)
#   --list              print what would be fetched and stop
#
# Needs curl or wget to install, and JavaScriptCore (jsc, ships with macOS) or
# Node 22.7+ to run.

set -eu

BASE=https://icosahedra.com
target=
list=0

while [ $# -gt 0 ]; do
  case $1 in
    --from) BASE=${2:-}; [ -n "$BASE" ] || { echo "install: --from needs a URL" >&2; exit 2; }; shift 2 ;;
    --from=*) BASE=${1#--from=}; shift ;;
    --list) list=1; shift ;;
    -h|--help) sed -n '2,20p' "$0" | sed 's/^# \{0,1\}//'; exit 0 ;;
    -*) echo "install: unknown option $1" >&2; exit 2 ;;
    *) target=$1; shift ;;
  esac
done
BASE=${BASE%/}
target=${target:-./nyx}

if command -v curl >/dev/null 2>&1; then
  fetch() { curl -fsSL "$1" -o "$2"; }
  fetch_stdout() { curl -fsSL "$1"; }
elif command -v wget >/dev/null 2>&1; then
  fetch() { wget -qO "$2" "$1"; }
  fetch_stdout() { wget -qO - "$1"; }
else
  echo "install: needs curl or wget" >&2
  exit 2
fi

manifest=$(fetch_stdout "$BASE/cli/manifest.txt") || {
  echo "install: cannot read $BASE/cli/manifest.txt" >&2
  exit 1
}
files=$(printf '%s\n' "$manifest" | sed 's/#.*//' | tr -d '\r' | awk 'NF')
[ -n "$files" ] || { echo "install: the manifest is empty" >&2; exit 1; }

# The list comes off the network, so it only ever names files below the target.
for path in $files; do
  case $path in
    /*|*..*|*'*'*) echo "install: refusing suspicious path in the manifest: $path" >&2; exit 1 ;;
  esac
done

count=$(printf '%s\n' "$files" | wc -l | tr -d ' ')
if [ "$list" = 1 ]; then
  printf '%s\n' "$files"
  echo "# $count files from $BASE" >&2
  exit 0
fi

echo "Installing $count files from $BASE into $target"
mkdir -p "$target"
done_count=0
for path in $files; do
  dir=$(dirname "$path")
  [ "$dir" = "." ] || mkdir -p "$target/$dir"
  if ! fetch "$BASE/$path" "$target/$path"; then
    echo "install: failed to fetch $BASE/$path" >&2
    exit 1
  fi
  [ -s "$target/$path" ] || { echo "install: $path came back empty" >&2; exit 1; }
  done_count=$((done_count + 1))
done
chmod +x "$target/nyx.sh"

launcher=$(cd "$target" && pwd)/nyx.sh
echo "Installed $done_count files."

JSC=/System/Library/Frameworks/JavaScriptCore.framework/Versions/Current/Helpers/jsc
if [ -x "$JSC" ]; then
  runtime="JavaScriptCore"
elif command -v node >/dev/null 2>&1; then
  runtime="Node $(node --version 2>/dev/null)"
else
  runtime=""
fi

if [ -n "$runtime" ]; then
  echo "Runtime: $runtime"
  echo
  echo "  $launcher --help"
  echo "  $launcher sdf logo.png --chan 3 --size 256"
  echo
  echo "Put it on PATH with:  ln -s $launcher /usr/local/bin/nyx"
else
  echo
  echo "No runtime found. nyx needs one of:" >&2
  echo "  - JavaScriptCore: ships with macOS at $JSC" >&2
  echo "  - Node 22.7 or newer (older versions need --experimental-detect-module)" >&2
  exit 1
fi
