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

repository="gakonst/nanocodex"
install_root="${NANOCODEX_DIR:-$HOME/.nanocodex}"
bin_dir="$install_root/bin"
versions_dir="$install_root/versions"
updater_dir="$install_root/updater"

case "$(uname -s)" in
  Linux) platform="unknown-linux-gnu" ;;
  Darwin) platform="apple-darwin" ;;
  *)
    echo "nanocodex: unsupported operating system $(uname -s)" >&2
    echo "Download a binary from https://github.com/$repository/releases/latest" >&2
    exit 1
    ;;
esac

case "$(uname -m)" in
  x86_64|amd64) architecture="x86_64" ;;
  arm64|aarch64) architecture="aarch64" ;;
  *)
    echo "nanocodex: unsupported architecture $(uname -m)" >&2
    exit 1
    ;;
esac

asset="nanocodex-${architecture}-${platform}"
temporary_dir="$(mktemp -d 2>/dev/null)" || {
  echo "nanocodex: failed to create a temporary directory" >&2
  exit 1
}
trap 'rm -rf -- "$temporary_dir"' EXIT

echo "Installing the latest Nanocodex release..."
release_redirect="$(
  curl --fail --silent --show-error --head \
    --output /dev/null --write-out '%{redirect_url}' \
    "https://github.com/$repository/releases/latest"
)"
release_tag="${release_redirect##*/}"
version="${release_tag#v}"
if [[ -z "$release_tag" || -z "$version" || "$version" == "$release_tag" ]]; then
  echo "nanocodex: could not resolve the latest release version" >&2
  exit 1
fi
release_url="https://github.com/$repository/releases/download/$release_tag"
curl --fail --silent --show-error --location "$release_url/$asset" --output "$temporary_dir/$asset"
curl --fail --silent --show-error --location "$release_url/SHA256SUMS" --output "$temporary_dir/SHA256SUMS"

expected="$(awk -v asset="$asset" '$2 == asset || $2 == "*" asset { print $1; exit }' "$temporary_dir/SHA256SUMS")"
if [[ -z "$expected" ]]; then
  echo "nanocodex: SHA256SUMS does not contain $asset" >&2
  exit 1
fi

if command -v sha256sum >/dev/null 2>&1; then
  actual="$(sha256sum "$temporary_dir/$asset" | awk '{ print $1 }')"
elif command -v shasum >/dev/null 2>&1; then
  actual="$(shasum -a 256 "$temporary_dir/$asset" | awk '{ print $1 }')"
else
  echo "nanocodex: sha256sum or shasum is required to verify the download" >&2
  exit 1
fi

if [[ "$actual" != "$expected" ]]; then
  echo "nanocodex: checksum mismatch for $asset" >&2
  exit 1
fi

version_dir="$versions_dir/$version"
mkdir -p "$bin_dir" "$version_dir" "$updater_dir"
install -m 755 "$temporary_dir/$asset" "$version_dir/nanocodex"
printf '%s\n' "$actual" > "$version_dir/nanocodex.sha256"
install -m 755 "$temporary_dir/$asset" "$updater_dir/nanocodex"

ln -sfn "versions/$version" "$install_root/current"

cat > "$temporary_dir/nanocodex-launcher" <<'EOF'
#!/bin/sh
set -eu

case "$0" in
    */*) launcher=$0 ;;
    *) launcher=$(command -v "$0") ;;
esac
bin_dir=$(CDPATH= cd -- "$(dirname -- "$launcher")" && pwd -P)
install_root=$(dirname -- "$bin_dir")

if [ "${1-}" = "update" ]; then
    export NANOCODEX_DIR="$install_root"
    exec "$install_root/updater/nanocodex" "$@"
fi
exec "$install_root/current/nanocodex" "$@"
EOF
install -m 755 "$temporary_dir/nanocodex-launcher" "$bin_dir/nanocodex"

path_line="export PATH=\"\$PATH:$bin_dir\""
profile=""
case "${SHELL:-}" in
  */zsh) profile="${ZDOTDIR:-$HOME}/.zshenv" ;;
  */bash) profile="$HOME/.bashrc" ;;
  */fish)
    profile="${XDG_CONFIG_HOME:-$HOME/.config}/fish/config.fish"
    path_line="fish_add_path -a \"$bin_dir\""
    ;;
  */ash|*/dash|*/ksh|*/sh) profile="$HOME/.profile" ;;
esac

if [[ ":$PATH:" != *":$bin_dir:"* && -n "$profile" ]]; then
  if [[ ( -e "$profile" || -L "$profile" ) && ! -w "$profile" ]]; then
    echo "nanocodex: cannot update $profile; add this line yourself:" >&2
    echo "  $path_line" >&2
  elif ! mkdir -p "$(dirname "$profile")" || ! touch "$profile"; then
    echo "nanocodex: cannot create $profile; add this line yourself:" >&2
    echo "  $path_line" >&2
  elif ! grep -Fq "$bin_dir" "$profile"; then
    if ! printf '\n# Nanocodex\n%s\n' "$path_line" >> "$profile"; then
      echo "nanocodex: cannot update $profile; add this line yourself:" >&2
      echo "  $path_line" >&2
    fi
  fi
fi

echo "Installed nanocodex $version to $version_dir/nanocodex"
echo "Activated it through $bin_dir/nanocodex"
if [[ ":$PATH:" != *":$bin_dir:"* ]]; then
  echo "Restart your shell or add $bin_dir to PATH."
fi
echo "Run 'nanocodex update' whenever you want the latest release."
