#!/usr/bin/env bash

set -euo pipefail

version=""
checksum=""
static_binary="false"
default_install_dir="/usr/local/bin"
install_dir="$default_install_dir"
download_dir=""
dev_build=""

print_help() {
    echo "Installs latest (or specific) version of babashka. Installation directory defaults to /usr/local/bin."
    echo -e
    echo "Usage:"
    echo "install [--dir <dir>] [--download-dir <download-dir>] [--version <version>] [--checksum <checksum>] [--static]"
    echo -e
    echo "Defaults:"
    echo " * Installation directory: ${default_install_dir}"
    echo " * Download directory: temporary"
    if [[ -z "$checksum" ]]; then
        echo " * Checksum: no"
    else
        echo " * Checksum: ${checksum}"
    fi
    echo " * Static binary: ${static_binary}"
    echo " * Version: <Latest release on github>"
    exit 1
}

while [[ $# -gt 0 ]]
do
    key="$1"
    case "$key" in
        --dir)
            install_dir="$2"
            shift
            shift
            ;;
        --download-dir)
            download_dir="$2"
            shift
            shift
            ;;
        --version)
            version="$2"
            shift
            shift
            ;;
        --checksum)
            checksum="$2"
            shift
            shift
            ;;
        --static)
            static_binary="true"
            shift
            ;;
        --dev-build)
            dev_build="true"
            shift
            ;;
        *)    # unknown option
            print_help
            shift
            ;;
    esac
done

if [[ -z "$download_dir" ]]; then
    download_dir="$(mktemp -d)"
    trap 'rm -rf "$download_dir"' EXIT
fi

if [[ "$checksum" != "" ]] && [[ "$version" == "" ]]; then
    >&2 echo "Options --checksum and --version should be provided together!"
    exit 1
fi

if [[ "$version" == "" ]]; then
    if [[ "$dev_build" == "true" ]]; then
        version="$(curl -sL https://raw.githubusercontent.com/babashka/babashka/master/resources/BABASHKA_VERSION)"
    else
        version="$(curl -sL https://raw.githubusercontent.com/babashka/babashka/master/resources/BABASHKA_RELEASED_VERSION)"
    fi
fi

case "$(uname -s)" in
    Linux*)  platform=linux;;
    Darwin*) platform=macos;;
esac

# Ugly ugly conversion of version to a comparable number
IFS='.' read -ra VER <<< "${version//-SNAPSHOT/}"
vernum=$(printf "%03d%03d%03d" "${VER[0]}" "${VER[1]}" "${VER[2]}")

case "$(uname -m)" in
    aarch64) arch=aarch64
             if [[ "$platform" == "linux" ]]; then
                 static_binary="true"
             fi
             ;;
    arm64) if [[ 10#$vernum -le 10#000008002 ]]; then
               arch="amd64"
           else
               arch="aarch64"
           fi
           ;;
    *) arch=amd64
       # always use static image on linux
       if [[ "$platform" == "linux" ]]; then
           static_binary="true"
       fi
       ;;
esac

if [[ 10#$vernum -le 10#000002013 ]]; then
    ext="zip"
    util="$(which unzip) -qqo"
else
    ext="tar.gz"
    util="$(which tar) -zxf"
fi

case "$platform-$static_binary" in
    linux-true) filename="babashka-$version-$platform-$arch-static."$ext
                ;;
    *-true)     >&2 echo "Static binaries are only available in Linux platform! Using the non-static one..."
                filename="babashka-$version-$platform-$arch."$ext
                ;;
    *)          filename="babashka-$version-$platform-$arch."$ext
                ;;
esac

if [[ "$version" == *-SNAPSHOT ]]
then
    repo="babashka-dev-builds"
else
    repo="babashka"
fi

download_url="https://github.com/babashka/$repo/releases/download/v$version/$filename"

# macOS only have shasum available by default
# Some Linux distros (RHEL-like) only have sha256sum available by default (others have both)
if command -v sha256sum >/dev/null; then
    sha256sum_cmd="sha256sum"
elif command -v shasum >/dev/null; then
    sha256sum_cmd="shasum -a 256"
else
    >&2 echo "Either 'sha256sum' or 'shasum' needs to be on PATH for '--checksum' flag!"
    >&2 echo "Exiting..."
    exit 1
fi

# Running this part in a subshell so when it finishes we go back to the previous directory
mkdir -p "$download_dir" && (
    cd "$download_dir"
    echo -e "Downloading $download_url to $download_dir"

    curl -o "$filename" -sL "$download_url"
    if [[ -n "$checksum" ]]; then
        if ! echo "$checksum *$filename" | $sha256sum_cmd --check --status; then
            >&2 echo "Failed checksum on $filename"
            >&2 echo "Got: $(shasum -a 256 "$filename" | cut -d' ' -f1)"
            >&2 echo "Expected: $checksum"
            exit 1
        fi
    fi
    $util "$filename"
    rm -f "$filename"
)

if [[ "$download_dir" != "$install_dir" ]]
then
    mkdir -p "$install_dir"
    if [ -f "$install_dir/bb" ]; then
        echo "Moving $install_dir/bb to $install_dir/bb.old"
        mv -f "$install_dir/bb" "$install_dir/bb.old"
    fi
    mv -f "$download_dir/bb" "$install_dir/bb"
fi

echo "Successfully installed bb in $install_dir"