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

platform=$(uname -ms)

if [[ ${OS:-} = Windows_NT ]]; then
  if [[ $platform != MINGW64* ]]; then
    powershell -c "irm ziex.dev/install.ps1|iex"
    exit $?
  fi
fi

# Reset
Color_Off=''

# Regular Colors
Red=''
Green=''
Dim='' # White

# Bold
Bold_Green=''

if [[ -t 1 ]]; then
    # Reset
    Color_Off='\033[0m' # Text Reset

    # Regular Colors
    Red='\033[0;31m'   # Red
    Green='\033[0;32m' # Green
    Dim='\033[0;2m'    # White

    # Bold
    Bold_Green='\033[1;32m' # Bold Green
    Bold_White='\033[1m'    # Bold White
fi

error() {
    echo -e "${Red}error${Color_Off}:" "$@" >&2
    exit 1
}

info() {
    echo -e "${Dim}$@ ${Color_Off}"
}

info_bold() {
    echo -e "${Bold_White}$@ ${Color_Off}"
}

success() {
    echo -e "${Green}$@ ${Color_Off}"
}

if [[ $# -gt 2 ]]; then
    error 'Too many arguments, only 2 are allowed. The first can be a specific tag of zx to install. (e.g. "zx-v0.1.4") The second can be a build variant of zx to install. (e.g. "debug-info")'
fi

case $platform in
'Darwin x86_64')
    target=macos-x64
    ;;
'Darwin arm64')
    target=macos-aarch64
    ;;
'Linux aarch64' | 'Linux arm64')
    target=linux-aarch64
    ;;
'MINGW64'*)
    target=windows-x64
    ;;
'Linux riscv64')
    error 'Not supported on riscv64'
    ;;
'Linux x86_64' | *)
    target=linux-x64
    ;;
esac

case "$target" in
'linux'*)
    if [ -f /etc/alpine-release ]; then
        target="$target-musl"
    fi
    ;;
esac

if [[ $target = darwin-x64 ]]; then
    # Is this process running in Rosetta?
    # redirect stderr to devnull to avoid error message when not running in Rosetta
    if [[ $(sysctl -n sysctl.proc_translated 2>/dev/null) = 1 ]]; then
        target=darwin-aarch64
        info "Your shell is running in Rosetta 2. Downloading zx for $target instead"
    fi
fi

# Determine archive format based on target platform
case "$target" in
'windows'*)
    archive_ext="zip"
    command -v unzip >/dev/null ||
        error 'unzip is required to install zx'
    ;;
*)
    archive_ext="tar.gz"
    command -v tar >/dev/null ||
        error 'tar is required to install zx'
    ;;
esac

GITHUB=${GITHUB-"https://github.com"}

github_repo="$GITHUB/nurulhudaapon/zx"

# If AVX2 isn't supported, use the -baseline build
case "$target" in
'darwin-x64'*)
    if [[ $(sysctl -a | grep machdep.cpu | grep AVX2) == '' ]]; then
        target="$target-baseline"
    fi
    ;;
'linux-x64'*)
    # If AVX2 isn't supported, use the -baseline build
    if [[ $(cat /proc/cpuinfo | grep avx2) = '' ]]; then
        target="$target-baseline"
    fi
    ;;
esac

exe_name=zx

if [[ $# = 2 && $2 = debug-info ]]; then
    target=$target-profile
    exe_name=zx-profile
    info "You requested a debug build of zx. More information will be shown if a crash occurs."
fi

if [[ $# = 0 ]]; then
    zx_uri=$github_repo/releases/latest/download/zx-$target.$archive_ext
else
    zx_uri=$github_repo/releases/download/$1/zx-$target.$archive_ext
fi

install_env=ZX_INSTALL
bin_env=\$$install_env/bin
install_dir=${!install_env:-$HOME/.zx}
bin_dir=$install_dir/bin
exe=$bin_dir/zx

if [[ ! -d $bin_dir ]]; then
    mkdir -p "$bin_dir" ||
        error "Failed to create install directory \"$bin_dir\""
fi

archive_file="$exe.$archive_ext"
curl --fail --location --progress-bar --output "$archive_file" "$zx_uri" ||
    error "Failed to download zx from \"$zx_uri\""

if [[ $archive_ext = "zip" ]]; then
    unzip -oqd "$bin_dir" "$archive_file" ||
        error 'Failed to extract zx'
else
    tar -xzf "$archive_file" -C "$bin_dir" ||
        error 'Failed to extract zx'
fi

# Remove existing zx executable if it exists
[[ -f "$exe" ]] && rm -f "$exe"
# Remove existing zx directory if it exists (shouldn't happen, but just in case)
[[ -d "$exe" ]] && rm -rf "$exe"

# Check if binary was extracted directly or in a subdirectory
extracted_binary=""
extracted_dir=""
if [[ -f "$bin_dir/zx-$target" ]]; then
    # Binary extracted directly (tar.gz case)
    extracted_binary="$bin_dir/zx-$target"
elif [[ -f "$bin_dir/zx-$target.exe" ]]; then
    # Windows binary extracted directly (zip case)
    extracted_binary="$bin_dir/zx-$target.exe"
elif [[ -f "$bin_dir/zx-$target/$exe_name" ]]; then
    # Binary in subdirectory (legacy structure)
    extracted_binary="$bin_dir/zx-$target/$exe_name"
    extracted_dir="$bin_dir/zx-$target"
else
    error "Could not find extracted zx binary in \"$bin_dir\""
fi

if [[ ! -f "$extracted_binary" ]]; then
    error "Expected executable \"$extracted_binary\" not found after extraction"
fi

mv "$extracted_binary" "$exe" ||
    error 'Failed to move extracted zx to destination'

chmod +x "$exe" ||
    error 'Failed to set permissions on zx executable'

# Clean up extracted directory if it exists, and archive file
if [[ -n "$extracted_dir" && -d "$extracted_dir" ]]; then
    rm -r "$extracted_dir"
fi
rm -f "$archive_file"

tildify() {
    if [[ $1 = $HOME/* ]]; then
        local replacement=\~/

        echo "${1/$HOME\//$replacement}"
    else
        echo "$1"
    fi
}

success "zx was installed successfully to $Bold_Green$(tildify "$exe")"

if command -v zx >/dev/null; then
    info_bold "Run 'zx --help' to get started"
    exit
fi

refresh_command=''

tilde_bin_dir=$(tildify "$bin_dir")
quoted_install_dir=\"${install_dir//\"/\\\"}\"

if [[ $quoted_install_dir = \"$HOME/* ]]; then
    quoted_install_dir=${quoted_install_dir/$HOME\//\$HOME/}
fi

echo

case $(basename "$SHELL") in
fish)
    commands=(
        "set --export $install_env $quoted_install_dir"
        "set --export PATH $bin_env \$PATH"
    )

    fish_config=$HOME/.config/fish/config.fish
    tilde_fish_config=$(tildify "$fish_config")

    if [[ -w $fish_config ]]; then
        if ! grep -q "$install_env" "$fish_config"; then
            {
                echo -e '\n# zx'

                for command in "${commands[@]}"; do
                    echo "$command"
                done
            } >>"$fish_config"
        fi

        refresh_command="source $tilde_fish_config"
    else
        echo "Manually add the directory to $tilde_fish_config (or similar):"

        for command in "${commands[@]}"; do
            info_bold "  $command"
        done
    fi
    ;;
zsh)
    commands=(
        "export $install_env=$quoted_install_dir"
        "export PATH=\"$bin_env:\$PATH\""
    )

    zsh_config=$HOME/.zshrc
    tilde_zsh_config=$(tildify "$zsh_config")

    if [[ -w $zsh_config ]]; then
        if ! grep -q "$install_env" "$zsh_config"; then
            {
                echo -e '\n# zx'

                for command in "${commands[@]}"; do
                    echo "$command"
                done
            } >>"$zsh_config"
        fi

        refresh_command="exec $SHELL"
    else
        echo "Manually add the directory to $tilde_zsh_config (or similar):"

        for command in "${commands[@]}"; do
            info_bold "  $command"
        done
    fi
    ;;
bash)
    commands=(
        "export $install_env=$quoted_install_dir"
        "export PATH=\"$bin_env:\$PATH\""
    )

    bash_configs=(
        "$HOME/.bash_profile"
        "$HOME/.bashrc"
    )

    if [[ ${XDG_CONFIG_HOME:-} ]]; then
        bash_configs+=(
            "$XDG_CONFIG_HOME/.bash_profile"
            "$XDG_CONFIG_HOME/.bashrc"
            "$XDG_CONFIG_HOME/bash_profile"
            "$XDG_CONFIG_HOME/bashrc"
        )
    fi

    set_manually=true
    for bash_config in "${bash_configs[@]}"; do
        tilde_bash_config=$(tildify "$bash_config")

        if [[ -w $bash_config ]]; then
            if ! grep -q "$install_env" "$bash_config"; then
                {
                    echo -e '\n# zx'

                    for command in "${commands[@]}"; do
                        echo "$command"
                    done
                } >>"$bash_config"
            fi

            refresh_command="source $bash_config"
            set_manually=false
            break
        fi
    done

    if [[ $set_manually = true ]]; then
        echo "Manually add the directory to $tilde_bash_config (or similar):"

        for command in "${commands[@]}"; do
            info_bold "  $command"
        done
    fi
    ;;
*)
    echo 'Manually add the directory to ~/.bashrc (or similar):'
    info_bold "  export $install_env=$quoted_install_dir"
    info_bold "  export PATH=\"$bin_env:\$PATH\""
    ;;
esac

if [[ $refresh_command ]]; then
    echo "Run to get started:"
    echo
    info "$refresh_command"
    info "zx --help"
fi