#!/usr/bin/env bash

set -euo pipefail

CLI_NAME="Automate"
CLI_EXECUTABLE="automate"
CLI_CONFIG_DIR=".automate"
CLI_REPO_LATEST_RELEASE_URL="https://api.github.com/repos/automatephp/automate/releases/latest"
CLI_DOWNLOAD_URL_PATTERN="https://github.com/automatephp/automate/releases/download/~latest_version~/automate-~platform~"
CLI_BINARY_TMP_NAME="$CLI_EXECUTABLE-"$(date +"%s")

main() {

    # Print ASCII logo
    ascii

    # Run environment check
    output "Environment check" "heading"
    third_party_check
    platform_check

    # Download binary
    output "Download" "heading"
    last_release_version
    download_binary
    executable_binary
    move_binary

    # Print informations
    output "\nThe ${CLI_NAME} v${latest_version} was installed successfully!" "success"

    if [ "$EUID" -ne 0 ]; then
        output "\nInstall it globally on your system:" "info"
        output "  mv ${binary_dest}/${CLI_EXECUTABLE} /usr/local/bin/${CLI_EXECUTABLE}"
    fi

    output "\nDon't forget to start a new shell to use ${CLI_NAME}" "info"
}

third_party_check() {
    # cURL or wget
    downloader=""
    if command -v curl >/dev/null 2>&1; then
        downloader="curl"
        output "  [*] cURL is installed" "success"
    elif command -v wget >/dev/null 2>&1; then
        downloader="wget"
        output "  [*] wget is installed" "success"
    else
        output "  [ ] ERROR: cURL or wget is required for installation." "error"
        exit 1
    fi
}

platform_check() {
    # OS (linux|darwin)
    local os=$(uname -s 2>/dev/null || /usr/bin/uname -s)
    case ${os} in
        "Linux"|"linux")
            os="linux"
            ;;
        "Darwin"|"darwin")
            os="darwin"
            ;;
        *)
            output "OS '${os}' not supported" "error"
            exit 1
            ;;
    esac
    output "  [*] Your OS (${os}) is supported" "success"

    # Arch (amd64)
    local arch=$(uname -m 2>/dev/null || /usr/bin/uname -m)
    case ${arch} in
        arm64)
            arch="arm64"
            ;;
        x86_64)
            arch="amd64"
            ;;
        *)
            output "  [ ] Your architecture (${arch}) is not currently supported" "error"
            exit 1
            ;;
    esac

    platform="${os}-${arch}"

    # Check if the platform combination is supported
    case ${platform} in
        "linux-amd64"|"darwin-arm64")
            output "  [*] Your platform (${platform}) is supported" "success"
            ;;
        "darwin-amd64")
            output "  [ ] macOS Intel (amd64) is no longer supported" "error"
            output "      Please use an Apple Silicon (arm64) device" "error"
            exit 1
            ;;
        "linux-arm64")
            output "  [ ] Linux ARM64 is not currently supported" "error"
            output "      Please use Linux AMD64" "error"
            exit 1
            ;;
        *)
            output "  [ ] Your platform (${platform}) is not currently supported" "error"
            exit 1
            ;;
    esac
}

last_release_version() {
    output "  Last release version..." "" " ";

    case ${downloader} in
        "curl")
            latest_version=$(curl -sS "$CLI_REPO_LATEST_RELEASE_URL" | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/')
            ;;
        "wget")
            latest_version=$(wget -q -nv -O- "$CLI_REPO_LATEST_RELEASE_URL" 2>/dev/null | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/')
            ;;
    esac

    if [ $? != 0 ]; then
        output "Failed to download LATEST version file: ${CLI_LATEST_VERSION_URL}" "error"
        exit 1
    fi

    output "ok" "success"
}

download_binary() {
    local latest_url=${CLI_DOWNLOAD_URL_PATTERN/~latest_version~/${latest_version}}
    latest_url=${latest_url/~platform~/${platform}}

    output "  Downloading binary..." "" " ";
    case ${downloader} in
        "curl")
            curl -sSf --location "${latest_url}" > "/tmp/${CLI_BINARY_TMP_NAME}"
            ;;
        "wget")
            wget -q "${latest_url}" -O "/tmp/${CLI_BINARY_TMP_NAME}"
            ;;
    esac

    if [ $? != 0 ]; then
        output "The download failed." "error"
        exit 1
    fi

    output "ok" "success"
}

executable_binary() {
    output "  Making the binary executable..." "" " "
    chmod 755 "/tmp/${CLI_BINARY_TMP_NAME}"
    output "ok" "success"
}

move_binary() {
    output "  Installing the binary..." "" " "

    if [ "$EUID" -eq 0 ]; then
        binary_dest="/usr/local/bin"
    else
        binary_dest="${HOME}/${CLI_CONFIG_DIR}/bin"
        if [ ! -d "${binary_dest}" ]; then
            if ! mkdir -p "${binary_dest}"; then
                binary_dest="."
            fi
        fi
    fi

    mv "/tmp/${CLI_BINARY_TMP_NAME}" "${binary_dest}/${CLI_EXECUTABLE}"

    if [ $? != 0 ]; then
        output "Failed to move the binary to ${binary_dest}." "error"
        rm "/tmp/${CLI_BINARY_TMP_NAME}"
        exit 1
    fi

    output "ok" "success"
}

ascii() {
    cat << "EOF"
   ___       __                  __
  / _ |__ __/ /____  __ _  ___ _/ /____
 / __ / // / __/ _ \/  ' \/ _ `/ __/ -_)
/_/ |_\_,_/\__/\___/_/_/_/\_,_/\__/\__/
EOF
}

output() {
    local style_start=""
    local style_end=""
    local carriage_return_start=""
    local carriage_return_end="${3:-"\\n"}"

    if [ "${2:-}" != "" ]; then
        case $2 in
            "success")
                style_start="\033[0;32m"
                style_end="\033[0m"
                ;;
            "error")
                style_start="\033[31;31m"
                style_end="\033[0m"
                ;;
            "info"|"warning")
                style_start="\033[33m"
                style_end="\033[39m"
                ;;
            "heading")
                carriage_return_start="\n"
                style_start="\033[1;33m"
                style_end="\033[22;39m"
                ;;
        esac
    fi

    builtin echo -ne "${carriage_return_start}${style_start}${1}${style_end}${carriage_return_end}"
}

main "$@"; exit