#!/bin/sh
#
# pilotlight installer — https://pilotlight.sh
#
#   curl -fsSL https://pilotlight.sh/install.sh | sh
#
# Environment:
#   PILOTLIGHT_VERSION       version to install, e.g. 0.1.0 (default: latest release)
#   PILOTLIGHT_INSTALL_DIR   where to put the binary   (default: $HOME/.local/bin)
#
# This script never runs sudo for you. If the install directory is not
# writable it tells you the command to run instead.
#
# Everything is wrapped in main() and invoked on the last line, so a
# truncated download cannot execute a partial script.

set -eu

REPO="cmoresid/pilotlight"
BIN="pilotlight"

# ---------------------------------------------------------------- output ----

if [ -t 1 ] && [ -z "${NO_COLOR:-}" ]; then
	C_RESET=$(printf '\033[0m')
	C_DIM=$(printf '\033[2m')
	C_BLUE=$(printf '\033[34m')
	C_RED=$(printf '\033[31m')
	C_YELLOW=$(printf '\033[33m')
	C_GREEN=$(printf '\033[32m')
else
	C_RESET='' C_DIM='' C_BLUE='' C_RED='' C_YELLOW='' C_GREEN=''
fi

say() { printf '%s\n' "$*"; }
step() { printf '%s==>%s %s\n' "$C_BLUE" "$C_RESET" "$*"; }
warn() { printf '%swarning:%s %s\n' "$C_YELLOW" "$C_RESET" "$*" >&2; }
die() {
	printf '%serror:%s %s\n' "$C_RED" "$C_RESET" "$*" >&2
	exit 1
}

has() { command -v "$1" >/dev/null 2>&1; }

need() {
	has "$1" || die "'$1' is required but was not found on PATH."
}

# ---------------------------------------------------------------- detect ----

detect_target() {
	os=$(uname -s)
	arch=$(uname -m)

	case "$arch" in
	x86_64 | amd64) arch=x86_64 ;;
	arm64 | aarch64) arch=aarch64 ;;
	*) die "unsupported architecture: $arch (pilotlight ships x86_64 and aarch64)" ;;
	esac

	case "$os" in
	Darwin)
		printf '%s-apple-darwin\n' "$arch"
		;;
	Linux)
		# Statically linked musl builds run on glibc systems too, but a
		# native glibc build is preferred where we can detect one.
		if ldd --version 2>&1 | grep -qi musl; then
			printf '%s-unknown-linux-musl\n' "$arch"
		else
			printf '%s-unknown-linux-gnu\n' "$arch"
		fi
		;;
	*)
		die "unsupported operating system: $os (pilotlight ships macOS and Linux builds)"
		;;
	esac
}

# -------------------------------------------------------------- download ----

# fetch <url> <destination-file>
fetch() {
	if has curl; then
		curl -fsSL --proto '=https' --tlsv1.2 -o "$2" "$1"
	elif has wget; then
		wget -qO "$2" "$1"
	else
		die "either curl or wget is required."
	fi
}

# fetch_stdout <url>
fetch_stdout() {
	if has curl; then
		curl -fsSL --proto '=https' --tlsv1.2 "$1"
	elif has wget; then
		wget -qO- "$1"
	else
		die "either curl or wget is required."
	fi
}

resolve_version() {
	if [ -n "${PILOTLIGHT_VERSION:-}" ]; then
		# Accept both "0.1.0" and "v0.1.0".
		printf '%s\n' "${PILOTLIGHT_VERSION#v}"
		return
	fi

	api="https://api.github.com/repos/$REPO/releases/latest"
	tag=$(fetch_stdout "$api" 2>/dev/null |
		sed -n 's/.*"tag_name"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' |
		head -n 1) || true

	[ -n "$tag" ] || die "could not determine the latest release of $REPO.

pilotlight may not have published a release yet, or the GitHub API may be
rate-limiting this address. Pin a version explicitly:

    curl -fsSL https://pilotlight.sh/install.sh | PILOTLIGHT_VERSION=0.1.0 sh"

	printf '%s\n' "${tag#v}"
}

# verify <file> <expected-sha256>
verify() {
	if has sha256sum; then
		actual=$(sha256sum "$1" | cut -d' ' -f1)
	elif has shasum; then
		actual=$(shasum -a 256 "$1" | cut -d' ' -f1)
	else
		die "neither sha256sum nor shasum was found; cannot verify the download."
	fi

	[ "$actual" = "$2" ] || die "checksum mismatch — refusing to install.

  expected  $2
  actual    $actual

This means the download was corrupted or tampered with. Nothing was installed."
}

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

main() {
	need uname
	need tar

	target=$(detect_target)
	version=$(resolve_version)
	dir=${PILOTLIGHT_INSTALL_DIR:-$HOME/.local/bin}

	archive="$BIN-v$version-$target.tar.gz"
	base="https://github.com/$REPO/releases/download/v$version"

	say ""
	say "  ${C_BLUE}pilotlight${C_RESET} v$version"
	say "  ${C_DIM}$target -> $dir${C_RESET}"
	say ""

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

	step "Downloading $archive"
	fetch "$base/$archive" "$tmp/$archive" ||
		die "download failed: $base/$archive

Check that v$version exists and ships a build for $target:
  https://github.com/$REPO/releases"

	step "Verifying checksum"
	fetch "$base/$archive.sha256" "$tmp/$archive.sha256" ||
		die "could not download the checksum file: $base/$archive.sha256"
	expected=$(cut -d' ' -f1 <"$tmp/$archive.sha256")
	[ -n "$expected" ] || die "the checksum file was empty."
	verify "$tmp/$archive" "$expected"

	step "Unpacking"
	tar -xzf "$tmp/$archive" -C "$tmp"
	[ -f "$tmp/$BIN" ] || die "the archive did not contain a '$BIN' binary."
	chmod +x "$tmp/$BIN"

	step "Installing to $dir"
	mkdir -p "$dir" 2>/dev/null || die "could not create $dir.

Choose a different location:
    curl -fsSL https://pilotlight.sh/install.sh | PILOTLIGHT_INSTALL_DIR=\$HOME/bin sh"

	if [ ! -w "$dir" ]; then
		die "$dir is not writable, and this installer will not run sudo for you.

Install somewhere you own:
    curl -fsSL https://pilotlight.sh/install.sh | PILOTLIGHT_INSTALL_DIR=\$HOME/.local/bin sh

Or download and place it yourself:
    curl -fLO $base/$archive
    tar -xzf $archive
    sudo install -m 755 $BIN $dir/$BIN"
	fi

	if has install; then
		install -m 755 "$tmp/$BIN" "$dir/$BIN"
	else
		cp "$tmp/$BIN" "$dir/$BIN"
		chmod 755 "$dir/$BIN"
	fi

	say ""
	say "  ${C_GREEN}✔${C_RESET} installed ${C_BLUE}$dir/$BIN${C_RESET}"

	case ":$PATH:" in
	*":$dir:"*) ;;
	*)
		say ""
		warn "$dir is not on your PATH."
		say ""
		say "  Add it to your shell profile:"
		say "    ${C_DIM}export PATH=\"$dir:\$PATH\"${C_RESET}"
		;;
	esac

	say ""
	say "  Next:"
	say "    ${C_DIM}pilotlight init${C_RESET}      scaffold a pilotlight.toml"
	say "    ${C_DIM}pilotlight start${C_RESET}     start everything in it"
	say ""
	say "  ${C_DIM}Docs: https://pilotlight.sh${C_RESET}"
	say ""
}

main "$@"
