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

FIRST_SOURCE_DIR="/opt/navi"
SECOND_SOURCE_DIR="${HOME}/.navi"

FIRST_BIN_DIR="/usr/bin"
SECOND_BIN_DIR="/usr/local/bin"

get_dir() {
   local -r first_dir="$1"
   local -r second_dir="$1"
   local -r useless_folder="${first_dir}/useless"
   local folder
   mkdir -p "$useless_folder" 2>/dev/null \
      && folder="$first_dir" \
      || folder="$second_dir"
   rm -r "$useless_folder" 2>/dev/null
   echo "$folder"
}

get_source_dir() {
   get_dir "$FIRST_SOURCE_DIR" "$SECOND_SOURCE_DIR"
}

get_bin_dir() {
   get_dir "$FIRST_BIN_DIR" "$SECOND_BIN_DIR"
}

echoerr() {
   echo "$@" 1>&2
}

command_exists() {
   type "$1" &>/dev/null
}

sha256() {
   if command_exists sha256sum; then
      sha256sum
   elif command_exists shasum; then
      shasum -a 256
   elif command_exists openssl; then
      openssl dgst -sha256
   else
      echoerr "Unable to calculate sha256!"
      exit 43
   fi
}

header() {
   echoerr "$*"
   echoerr
}

latest_version_released() {
   curl -s 'https://api.github.com/repos/denisidoro/navi/releases/latest' \
      | grep -Eo 'releases/tag/v([0-9\.]+)' \
      | sed 's|releases/tag/v||'
}

asset_url() {
   local -r version="$1"
   local -r variant="${2:-}"

   if [[ -n "$variant" ]]; then
      echo "https://github.com/denisidoro/navi/releases/download/v${version}/navi-${variant}.tar.gz"
   else
      echo "https://github.com/denisidoro/navi/archive/v${version}.tar.gz"
   fi
}

download_asset() {
   local -r url="$(asset_url "$@")"
   mkdir -p "$SOURCE_DIR"
   cd "$SOURCE_DIR"
   rm -f navi.tar.gz
   echoerr "Downloading ${url}..."
   curl -L "$url" -o navi.tar.gz
   tar xvzf navi.tar.gz
   rm -f navi.tar.gz
   ln -s "${SOURCE_DIR}/navi" "${BIN_DIR}/navi"
}

sha_for_asset_on_github() {
   local -r url="$(asset_url "$@")"
   curl -sL "$url" | sha256 | awk '{print $1}'
}

get_target() {
   local -r unamea="$(uname -a)"
   local -r archi="$(uname -sm)"
   local is_android

   [[ $unamea = *Android* ]] && is_android=true || is_android=false

   local target
   case "$archi" in
      Darwin*) target="x86_64-osx" ;;
      Linux\ *x86*) is_android && target="aarch64-linux-android" || target="x86_64-unknown-linux-musl" ;;
      *arm*) is_android && target="armv7-linux-androideabi" || target="armv7-unknown-linux-musleabihf" ;;
      *) target="" ;;
   esac

   echo "$target"
}

no_binary_warning() {
   echoerr "There's no precompiled binary for your platform: $(uname -a)"
}

get_shell() {
   echo $SHELL | xargs basename
}

install_navi() {
   export SOURCE_DIR="${SOURCE_DIR:-"$(get_source_dir)"}"
   export BIN_DIR="${BIN_DIR:-"$(get_bin_dir)"}"
   echoerr "Sources will be downloaded to ${SOURCE_DIR}..."

   local -r target="$(get_target)"

   if [[ -n "$target" ]]; then
      local -r version="$(latest_version_released)"
      download_asset "$version" "$target"

   elif command_exists cargo; then
      no_binary_warning
      echoerr "Building sources..."
      git clone https://github.com/denisidoro/navi "$SOURCE_DIR"
      cd "$SOURCE_DIR"
      make install

   else
      no_binary_warning
      echoerr "You don't have the necessary tools to build it"
      echoerr "Please open an issue at https://github.com/denisidoro/navi"
      echoerr "Aborting..."
      exit 33
   fi

   local -r shell="$(get_shell)"
   echoerr -e "Finished. To call navi, restart your shell or reload the config file:\n   source ~/.${shell}rc"
   echoerr -e "\nTo add the Ctrl-G keybinding, add the following to ~/.${shell}rc:\n   source \"$(navi widget ${shell})\""
   return 0
}

(return 0 2>/dev/null) || install_navi "$@"
