#!/bin/sh
# Install Spooligan, the command-line tool that prints receipts on thermal printers.
#
#   curl -fsSL https://spooligan.ai/install.sh | sh
#
# It downloads the build for this computer (Linux on 64-bit Intel/AMD or ARM, or macOS), checks it against the
# published SHA-256 checksums, and installs it as `spooligan` in /usr/local/bin, or in ~/.local/bin when it can't
# write there. Settings:
#   SPOOLIGAN_INSTALL_DIR   install into this folder instead
#   SPOOLIGAN_BASE_URL      download from here instead of https://spooligan.ai/download
set -eu

base=${SPOOLIGAN_BASE_URL:-https://spooligan.ai/download}
base=${base%/}

say() { printf '%s\n' "$*"; }
die() { printf 'spooligan install: %s\n' "$*" >&2; exit 1; }

# ---------------------------------------------------------------- which build
os=$(uname -s)
arch=$(uname -m)
case $os in
Linux)
	case $arch in
	x86_64 | amd64) file=spooligan-linux-amd64 ;;
	aarch64 | arm64) file=spooligan-linux-arm64 ;;
	*) die "there's no Linux build for $arch yet (only 64-bit Intel/AMD and ARM)" ;;
	esac
	;;
Darwin)
	# A signed, notarized build for Apple silicon or for Intel. The installer at
	# https://spooligan.ai/download/Spooligan.pkg works on both, and most people on a Mac will find it easier.
	# A shell running under Rosetta reports x86_64 on Apple silicon; the native build is the better one there.
	if [ "$arch" = x86_64 ] && [ "$(sysctl -n sysctl.proc_translated 2>/dev/null || true)" = 1 ]; then
		arch=arm64
	fi
	case $arch in
	arm64 | aarch64) file=spooligan-macos-arm64 ;;
	x86_64 | amd64) file=spooligan-macos-amd64 ;;
	*) die "there's no macOS build for $arch (only Apple silicon and Intel)" ;;
	esac
	;;
MINGW* | MSYS* | CYGWIN* | Windows_NT) die "Windows isn't supported by this installer yet" ;;
*) die "there's no build for $os yet" ;;
esac

# ---------------------------------------------------------------- tools
if command -v curl >/dev/null 2>&1; then
	fetch() { curl -fsSL --proto '=https,http' -o "$2" "$1"; }
elif command -v wget >/dev/null 2>&1; then
	fetch() { wget -q -O "$2" "$1"; }
else
	die "this needs curl or wget to download Spooligan"
fi
if command -v sha256sum >/dev/null 2>&1; then
	sha256() { sha256sum "$1" | cut -d' ' -f1; }
elif command -v shasum >/dev/null 2>&1; then
	sha256() { shasum -a 256 "$1" | cut -d' ' -f1; }
else
	die "this needs sha256sum or shasum to check the download"
fi

tmp=$(mktemp -d 2>/dev/null || mktemp -d -t spooligan)
trap 'rm -rf "$tmp"' EXIT INT TERM

# ---------------------------------------------------------------- download and check
say "Downloading $file..."
fetch "$base/$file" "$tmp/spooligan" || die "couldn't download $base/$file"
fetch "$base/SHA256SUMS" "$tmp/SHA256SUMS" || die "couldn't download $base/SHA256SUMS"
want=$(awk -v f="$file" '$2 == f || $2 == "*" f { print $1; exit }' "$tmp/SHA256SUMS")
[ -n "$want" ] || die "SHA256SUMS has no line for $file"
got=$(sha256 "$tmp/spooligan")
[ "$got" = "$want" ] || die "the download doesn't match its checksum (got $got, want $want); nothing was installed"
say "Checksum OK."
chmod 755 "$tmp/spooligan"

# ---------------------------------------------------------------- install
# Into the given folder; else /usr/local/bin, with sudo only when this user can't write there; else ~/.local/bin.
install_to() { # DIR [sudo]
	if [ "${2:-}" = sudo ]; then
		sudo mkdir -p "$1" && sudo cp "$tmp/spooligan" "$1/spooligan.new" && sudo mv -f "$1/spooligan.new" "$1/spooligan"
	else
		mkdir -p "$1" && cp "$tmp/spooligan" "$1/spooligan.new" && mv -f "$1/spooligan.new" "$1/spooligan"
	fi
}
if [ -n "${SPOOLIGAN_INSTALL_DIR:-}" ]; then
	dir=$SPOOLIGAN_INSTALL_DIR
	install_to "$dir" || die "couldn't install into $dir"
else
	dir=/usr/local/bin
	if { [ -d "$dir" ] && [ -w "$dir" ]; } || { [ ! -e "$dir" ] && [ -w /usr/local ]; }; then
		install_to "$dir" || die "couldn't install into $dir"
	elif command -v sudo >/dev/null 2>&1 && { sudo -n true 2>/dev/null || [ -r /dev/tty ]; }; then
		say "Installing into $dir needs administrator rights, so sudo may ask for your password."
		say "(To skip that, run with SPOOLIGAN_INSTALL_DIR=\$HOME/.local/bin.)"
		if ! install_to "$dir" sudo; then
			dir=$HOME/.local/bin
			say "That didn't work; installing into $dir instead."
			install_to "$dir" || die "couldn't install into $dir"
		fi
	else
		dir=$HOME/.local/bin
		install_to "$dir" || die "couldn't install into $dir"
	fi
fi
say "Installed $dir/spooligan"
v=$("$dir/spooligan" version 2>/dev/null | cut -d" " -f1-2) && [ -n "$v" ] && say "$v" || true

# ---------------------------------------------------------------- next steps
case ":$PATH:" in
*":$dir:"*) cmd=spooligan ;;
*)
	cmd="$dir/spooligan"
	say ""
	say "$dir isn't on your PATH yet. Add this line to your shell's startup file (~/.profile, ~/.bashrc or ~/.zshrc):"
	say "  export PATH=\"$dir:\$PATH\""
	;;
esac
say ""
say "Next:"
say "  $cmd printer setup         find your USB receipt printer (plug it in first)"
say "  $cmd hello                 print a welcome page; add -o hello.png for a picture"
say "  $cmd --help                every command"
say "  $cmd agents                the guide for your AI agent"
if [ "$os" = Linux ]; then
	say ""
	say "USB printers on Linux: to print without sudo, allow your printer with a udev rule. Its ids come from"
	say "\`$cmd printer list --scan\`, and \`$cmd agents install\` shows the exact commands."
fi
