#!/bin/bash
#
# Goldsky CLI installation script
#
# Downloads and installs a binary from the given url.
#
# This script is inspired by the installation script
# for https://www.jetpack.io/devbox.

set -euo pipefail

# ========================
# Customize install script
# ========================

# This script is published at cli.goldsky.com/install so users can install via:
# curl -fsSL https://cli.goldsky.com/install | bash

readonly INSTALL_DIR="/usr/local/bin"
readonly BIN="goldsky"
readonly DOWNLOAD_BASE_URL="https://cli.goldsky.com/latest"

readonly TITLE="Goldsky CLI"
readonly DESCRIPTION=$(
	cat <<EOF
  Crypto Data Live-Streamed

  This script downloads and installs the latest Goldsky CLI binary.
EOF
)
readonly DOCS_URL="https://docs.goldsky.com/"
readonly CHANGELOG_URL="https://goldsky.com/changelog"
readonly SUPPORT_EMAIL="support@goldsky.com"
readonly X_PROFILE_URL="https://x.com/goldskyio"

# ====================
# flags.sh
# ====================
FORCE="${FORCE:-0}"

parse_flags() {
	while [ "$#" -gt 0 ]; do
		case "$1" in
		-f | --force)
		FORCE=1
		shift 1
		;;
		*)
		error "Unknown option: $1"
		exit 1
		;;
		esac
	done
}

# ====================
# format.sh
# ====================

readonly BOLD="$(tput bold 2>/dev/null || echo '')"
readonly GREY="$(tput setaf 8 2>/dev/null || echo '')"
readonly UNDERLINE="$(tput smul 2>/dev/null || echo '')"
readonly RED="$(tput setaf 1 2>/dev/null || echo '')"
readonly GREEN="$(tput setaf 2 2>/dev/null || echo '')"
readonly YELLOW="$(tput setaf 3 2>/dev/null || echo '')"
readonly BLUE="$(tput setaf 4 2>/dev/null || echo '')"
readonly CYAN="$(tput setaf 6 2>/dev/null || echo '')"
readonly ORANGE="$(tput setaf 166 2>/dev/null || echo '')"
readonly NO_COLOR="$(tput sgr0 2>/dev/null || echo '')"
readonly CLEAR_LAST_MSG="\033[1F\033[0K"

title() {
	local -r text="$*"
	printf "%s\n" "${BOLD}${ORANGE}${text}${NO_COLOR}"
}

header() {
	local -r text="$*"
	printf "%s\n" "${BOLD}${text}${NO_COLOR}"
}

plain() {
	local -r text="$*"
	printf "%s\n" "${text}"
}

info() {
	local -r text="$*"
	printf "%s\n" "${BOLD}${GREY}→${NO_COLOR} ${text}"
}

warn() {
	local -r text="$*"
	printf "%s\n" "${YELLOW}! $*${NO_COLOR}"
}

error() {
	local -r text="$*"
	printf "%s\n" "${RED}✘ ${text}${NO_COLOR}" >&2
}

success() {
	local -r text="$*"
	printf "%s\n" "${GREEN}✓${NO_COLOR} ${text}"
}

start_task() {
	local -r text="$*"
	printf "%s\n" "${BOLD}${GREY}→${NO_COLOR} ${text}..."
}

end_task() {
	local -r text="$*"
	printf "${CLEAR_LAST_MSG}%s\n" "${GREEN}✓${NO_COLOR} ${text}... [DONE]"
}

fail_task() {
	local -r text="$*"
	printf "${CLEAR_LAST_MSG}%s\n" "${RED}✘ ${text}... [FAILED]${NO_COLOR}" >&2
}

confirm() {
	if [ ${FORCE-} -ne 1 ]; then
		printf "%s " "${ORANGE}?${NO_COLOR} $* ${BOLD}[Y/n]${NO_COLOR}"
		set +e
		read -r yn </dev/tty
		rc=$?
		set -e
		if [ $rc -ne 0 ]; then
			error "Error reading from prompt (re-run with '-f' flag to auto select Yes if running in a script)"
			exit 1
		fi
		if [ "$yn" != "y" ] && [ "$yn" != "Y" ] && [ "$yn" != "yes" ] && [ "$yn" != "" ]; then
			error 'Aborting (please answer "yes" to continue)'
			exit 1
		fi
	fi
}

delay() {
	sleep 0.3
}

# =========
# util.sh
# =========
has() {
	command -v "$1" 1>/dev/null 2>&1
}

download() {
	local -r url="$1"
	local -r file="$2"
	local cmd=""

	if has curl; then
		cmd="curl --fail --silent --location --output $file $url"
	elif has wget; then
		cmd="wget --quiet --output-document=$file $url"
	elif has fetch; then
		cmd="fetch --quiet --output=$file $url"
	else
		error "No program to download files found. Please install one of: curl, wget, fetch"
		error "Exiting..."
		return 1
	fi

	if [[ ${3:-} == "--fail" ]]; then
		$cmd && return 0 || rc=$?
		error "Command failed (exit code $rc): ${BLUE}${cmd}${NO_COLOR}"
		exit $rc
	fi

	$cmd && return 0 || rc=$?
	return $rc
}

detect_platform() {
  local os="$(uname -s | tr '[:upper:]' '[:lower:]')"
  local arch="$(uname -m)"

  case "${os}" in
		msys_nt*) os="win" ;;
		cygwin_nt*) os="win" ;;
		mingw*) os="win" ;;
		darwin*) os="macos" ;;
  esac

  # Detect architecture
  case "${os}" in
    macos)
      # hw.optional.arm64 is the only sysctl key that reliably returns 1 on
      # Apple Silicon even under Rosetta (uname -m lies in that context)
      if [ "$(sysctl -n hw.optional.arm64 2>/dev/null)" = "1" ]; then
        arch="arm64"
      else
        arch="x64"
      fi
      printf '%s' "${os}-${arch}"
      ;;
    linux)
      case "${arch}" in
        aarch64|arm64) arch="arm64" ;;
        *) arch="x64" ;;
      esac
      printf '%s' "${os}-${arch}"
      ;;
    *)
      # Windows and others: no arch suffix
      printf '%s' "${os}"
      ;;
  esac
}

get_download_url() {
  local -r platform="$(detect_platform)"
  local downloadUrl="${DOWNLOAD_BASE_URL}/${platform}/goldsky"

  if [[ "$platform" == win* ]]; then
    downloadUrl="${downloadUrl}.exe"
  fi

  printf '%s' "${downloadUrl}"
}

DOWNLOAD_URL=$(get_download_url)

# ==============
# Implementation
# ==============
intro_msg() {
	title "${TITLE}"
	plain "${DESCRIPTION}"
	printf "\n"
	header "Confirm Installation Details"
	plain "  Location:     ${GREEN}${INSTALL_DIR}/${BIN}${NO_COLOR}"
	plain "  Download URL: ${UNDERLINE}${BLUE}${DOWNLOAD_URL}${NO_COLOR}"
	printf "\n"
}

install_flow() {
	confirm "Install ${GREEN}${BIN}${NO_COLOR} to ${GREEN}${INSTALL_DIR}${NO_COLOR} (requires sudo)?"
	printf "\n"
	header "Downloading and Installing"

	start_task "Downloading ${BIN} binary"
	local -r tmp_file=$(mktemp)
	download "${DOWNLOAD_URL}" "${tmp_file}" --fail
	delay
	end_task "Downloading ${BIN} binary"

	start_task "Installing in ${INSTALL_DIR}/${BIN} (requires sudo)"
	chmod +x "${tmp_file}"
	$(command -v sudo || true) bash -c "mkdir -p ${INSTALL_DIR} && mv ${tmp_file} ${INSTALL_DIR}/${BIN}"
	delay
	end_task "Installing in ${INSTALL_DIR}/${BIN}"
	delay

	success "${BOLD}Successfully installed ${GREEN}${BIN}${NO_COLOR}${BOLD}${NO_COLOR} 🚀"
	delay
	printf "\n"
}

next_steps_msg() {
	header "Next Steps"
	plain "  1. ${BOLD}Learn how to use ${BIN}${NO_COLOR}"
	plain "     ${GREY}Run ${CYAN}${BIN}${GREY} or read the docs at ${UNDERLINE}${BLUE}${DOCS_URL}${NO_COLOR}"
	plain "  2. ${BOLD}Get help and give feedback${NO_COLOR}"
	plain "     ${GREY}Email us at ${SUPPORT_EMAIL} and follow us at ${UNDERLINE}${BLUE}${X_PROFILE_URL}${NO_COLOR}"
 	plain "  3. ${BOLD}Stay up to date with product features${NO_COLOR}"
	plain "     ${GREY}Check out the Goldsky change log ${UNDERLINE}${BLUE}${CHANGELOG_URL}${NO_COLOR}"
}

main() {
	parse_flags "$@"
	intro_msg
	install_flow
	next_steps_msg
}

main "$@"
