#!/usr/bin/env bash
set -euo pipefail

APP_NAME="jam"
DIST_REPO="jhl-labs/dist"
DIST_API="https://api.github.com/repos/${DIST_REPO}/releases?per_page=100"
LATEST_TAG="jam-v0.46.0"
INSTALL_DIR="${INSTALL_DIR:-/usr/local/bin}"
BIN_NAME="${BIN_NAME:-jam}"
REQUESTED_VERSION="${VERSION:-latest}"

log() {
  printf '%s\n' "$*" >&2
}

need() {
  if ! command -v "$1" >/dev/null 2>&1; then
    log "error: required command not found: $1"
    exit 1
  fi
}

need awk
need curl
need id
need install
need mktemp
need sed
need tr
need uname

if command -v sha256sum >/dev/null 2>&1; then
  checksum_verify() {
    sha256sum -c "$1"
  }
elif command -v shasum >/dev/null 2>&1; then
  checksum_verify() {
    shasum -a 256 -c "$1"
  }
else
  log "error: required command not found: sha256sum or shasum"
  exit 1
fi

os="$(uname -s | tr '[:upper:]' '[:lower:]')"
case "$os" in
  linux | darwin) ;;
  *)
    log "error: ${APP_NAME} install script supports Linux and macOS; detected ${os}"
    exit 1
    ;;
esac

machine="$(uname -m)"
case "$machine" in
  x86_64 | amd64) arch="amd64" ;;
  aarch64 | arm64) arch="arm64" ;;
  *)
    log "error: unsupported architecture: ${machine}"
    exit 1
    ;;
esac

latest_tag() {
  local releases line tag
  if [ -n "$LATEST_TAG" ]; then
    printf '%s\n' "$LATEST_TAG"
    return 0
  fi
  releases="$(curl -fsSL "$DIST_API")"
  while IFS= read -r line; do
    case "$line" in
      *'"tag_name"'*'"jam-v'*)
        tag="$(printf '%s\n' "$line" | sed -n 's/.*"tag_name"[[:space:]]*:[[:space:]]*"\(jam-v[^"]*\)".*/\1/p')"
        if [ -n "$tag" ]; then
          printf '%s\n' "$tag"
          return 0
        fi
        ;;
    esac
  done <<< "$releases"
}

normalize_tag() {
  case "$1" in
    latest) latest_tag ;;
    jam-v*) printf '%s\n' "$1" ;;
    v*) printf 'jam-%s\n' "$1" ;;
    *) printf 'jam-v%s\n' "$1" ;;
  esac
}

dist_tag="$(normalize_tag "$REQUESTED_VERSION")"
if [ -z "$dist_tag" ]; then
  log "error: could not discover latest ${APP_NAME} release from ${DIST_REPO}"
  exit 1
fi

version="${dist_tag#jam-}"
asset="${APP_NAME}_${version}_${os}_${arch}"
release_base="https://github.com/${DIST_REPO}/releases/download/${dist_tag}"
tmp_dir="$(mktemp -d)"
cleanup() {
  rm -rf "$tmp_dir"
}
trap cleanup EXIT

log "installing ${APP_NAME} ${version} for ${os}/${arch}"
curl -fsSL "${release_base}/${asset}" -o "${tmp_dir}/${asset}"
curl -fsSL "${release_base}/SHA256SUMS" -o "${tmp_dir}/SHA256SUMS"

(
  cd "$tmp_dir"
  if ! awk -v asset="$asset" '$2 == asset { print; found = 1 } END { exit found ? 0 : 1 }' SHA256SUMS > SHA256SUMS.selected; then
    log "error: checksum entry not found for ${asset}"
    exit 1
  fi
  checksum_verify SHA256SUMS.selected
)

chmod +x "${tmp_dir}/${asset}"

if [ "$(id -u)" -eq 0 ]; then
  install -d -m 0755 "$INSTALL_DIR"
  install -m 0755 "${tmp_dir}/${asset}" "${INSTALL_DIR}/${BIN_NAME}"
elif install -d -m 0755 "$INSTALL_DIR" 2>/dev/null && install -m 0755 "${tmp_dir}/${asset}" "${INSTALL_DIR}/${BIN_NAME}" 2>/dev/null; then
  :
else
  need sudo
  sudo install -d -m 0755 "$INSTALL_DIR"
  sudo install -m 0755 "${tmp_dir}/${asset}" "${INSTALL_DIR}/${BIN_NAME}"
fi

log "installed ${INSTALL_DIR}/${BIN_NAME}"
"${INSTALL_DIR}/${BIN_NAME}" --version
