#!/bin/sh
# Install huh from GitHub releases.
#
# Usage:
#   curl -LsSf https://olisemeka.dev/huh/install.sh | sh
#
# Environment:
#   HUH_INSTALL_DIR  install directory (default: $HOME/.local/bin)
#   HUH_VERSION      release tag, for example v0.1.0 (default: latest)
#   HUH_TARGET       override the detected release target
#   HUH_BASE_URL     override the download base (mirrors and local testing)

set -eu

REPO="OliseNS/huh"
BIN="huh"
ASSET=""
TARGET=""
TMP_DIR=""
TMP_BIN=""

cleanup() {
  [ -n "$TMP_BIN" ] && rm -f "$TMP_BIN"
  [ -n "$TMP_DIR" ] && rm -rf "$TMP_DIR"
}
trap cleanup EXIT HUP INT TERM

fail() {
  echo "error: $*" >&2
  exit 1
}

if [ -z "${HOME:-}" ] && [ -z "${HUH_INSTALL_DIR:-}" ]; then
  fail "HOME is not set; pass HUH_INSTALL_DIR"
fi

INSTALL_DIR="${HUH_INSTALL_DIR:-${HOME}/.local/bin}"

if command -v curl >/dev/null 2>&1; then
  DOWNLOADER="curl"
elif command -v wget >/dev/null 2>&1; then
  DOWNLOADER="wget"
else
  fail "curl or wget is required"
fi

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

  case "$os" in
    Linux)
      case "$arch" in
        x86_64 | amd64) echo "x86_64-unknown-linux-musl" ;;
        aarch64 | arm64) echo "aarch64-unknown-linux-musl" ;;
        *) fail "unsupported Linux architecture: $arch" ;;
      esac
      ;;
    Darwin)
      case "$arch" in
        x86_64 | amd64) echo "x86_64-apple-darwin" ;;
        arm64 | aarch64) echo "aarch64-apple-darwin" ;;
        *) fail "unsupported macOS architecture: $arch" ;;
      esac
      ;;
    *)
      fail "unsupported operating system: $os; see https://github.com/${REPO}/releases"
      ;;
  esac
}

if [ -n "${HUH_TARGET:-}" ]; then
  TARGET="$HUH_TARGET"
else
  TARGET="$(detect_target)"
fi

ASSET="${BIN}-${TARGET}.tar.gz"

if [ -n "${HUH_BASE_URL:-}" ]; then
  BASE_URL="${HUH_BASE_URL%/}"
elif [ -n "${HUH_VERSION:-}" ]; then
  case "$HUH_VERSION" in
    v*) TAG="$HUH_VERSION" ;;
    *) TAG="v$HUH_VERSION" ;;
  esac
  BASE_URL="https://github.com/${REPO}/releases/download/${TAG}"
else
  BASE_URL="https://github.com/${REPO}/releases/latest/download"
fi

TMP_DIR="$(mktemp -d)" || fail "could not create a temporary directory"

download() {
  if [ "$DOWNLOADER" = "curl" ]; then
    curl -fLsS "$1" -o "$2"
  else
    wget -q "$1" -O "$2"
  fi
}

echo "Downloading ${ASSET}..."
download "${BASE_URL}/${ASSET}" "${TMP_DIR}/${ASSET}" ||
  fail "could not download ${BASE_URL}/${ASSET}"

download "${BASE_URL}/sha256sums.txt" "${TMP_DIR}/sha256sums.txt" ||
  fail "could not download ${BASE_URL}/sha256sums.txt"
EXPECTED="$(awk -v asset="$ASSET" '$2 == asset { print $1; exit }' "${TMP_DIR}/sha256sums.txt")"
[ -n "$EXPECTED" ] || fail "no checksum for ${ASSET}"

if command -v sha256sum >/dev/null 2>&1; then
  ACTUAL="$(sha256sum "${TMP_DIR}/${ASSET}" | awk '{ print $1 }')"
elif command -v shasum >/dev/null 2>&1; then
  ACTUAL="$(shasum -a 256 "${TMP_DIR}/${ASSET}" | awk '{ print $1 }')"
else
  fail "sha256sum or shasum is required to verify the download"
fi

[ "$ACTUAL" = "$EXPECTED" ] || fail "checksum verification failed for ${ASSET}"

tar -xzf "${TMP_DIR}/${ASSET}" -C "$TMP_DIR" || fail "could not extract ${ASSET}"
BIN_PATH="$(find "$TMP_DIR" -type f -name "$BIN" -perm -0100 | head -n 1)"
[ -n "$BIN_PATH" ] || fail "could not find ${BIN} in ${ASSET}"

mkdir -p "$INSTALL_DIR" || fail "could not create ${INSTALL_DIR}"
TMP_BIN="${INSTALL_DIR}/.${BIN}.$$.tmp"
cp "$BIN_PATH" "$TMP_BIN" || fail "could not write to ${INSTALL_DIR}"
chmod 0755 "$TMP_BIN" || fail "could not set permissions on ${TMP_BIN}"
mv -f "$TMP_BIN" "${INSTALL_DIR}/${BIN}" || fail "could not install ${BIN}"
TMP_BIN=""

echo "Installed ${BIN} to ${INSTALL_DIR}/${BIN}"
case ":${PATH}:" in
  *":${INSTALL_DIR}:"*) ;;
  *) echo "Add ${INSTALL_DIR} to your PATH to run ${BIN} from anywhere." ;;
esac
echo "Run: ${BIN} why is the sky blue?"
