#!/bin/bash
set -e

install_dir="${PREFIX:-/usr/local}/bin"
tmp_path="${TMPDIR:-/tmp}"
add_alias=${ALIAS:-0}
nightly=${NIGHTLY:-0}
debug=${DEBUG:-0}
verify=${VERIFY:-0}
local=${LOCAL:-0}
use_sudo=${USE_SUDO:-0}
force_update=${FORCE_UPDATE:-0}

usage() {
    echo "Options:"
    echo
    echo "  -a, --alias               Create/update 'f' alias"
    echo "  -n, --nightly             Latest nightly build"
    echo "  -D, --debug               Debug build"
    echo "  -d <path>, --dest <path>  Set install destination (default /usr/local/bin)"
    echo "  -V, --verify              Verify gpg signature"
    echo "  -l, --local               Verify gpg signature with local keychain"
    echo "  -F, --force               Force re-install even if flow is up-to-date"
    exit 1
}

while true; do
    case "${1}" in
    -a | --alias)
        add_alias=1
        shift 1
        ;;
    -n | --nightly)
        nightly=1
        shift 1
        ;;
    -D | --debug)
        debug=1
        shift 1
        ;;
    -d | --dest)
        install_dir=$2
        shift 2
        ;;
    -V | --verify)
        verify=1
        shift 1
        ;;
    -l | --local)
        local=1
        shift 1
        ;;
    -F | --force)
        force_update=1
        shift 1
        ;;
    -h | --help)
        usage
        ;;
    --)
        shift 1
        break
        ;;
    "")
        break
        ;;
    *)
        echo error: Unknown argument "${1}"
        echo
        usage
        ;;
    esac
done

have_term=0
if [ -t 0 ]; then
    have_term=1
fi

need_sudo=""
if [ ! -w "$install_dir" ]; then
    need_sudo="$install_dir"
fi

if [ -z "$need_sudo" ] && [ -e "$install_dir/flow" ]; then
    if [ ! -w "$install_dir/flow" ]; then
        need_sudo="$install_dir/flow"
    fi
fi

if [ -z "$need_sudo" ] && [ -e "$install_dir/f" ]; then
    if [ ! -w "$install_dir/f" ]; then
        need_sudo="$install_dir/f"
    fi
fi

# prompt for nightly build option if interactive
if [ "$nightly" -eq 0 ] && [ "$have_term" -eq 1 ]; then
    printf "do you want to install a Nightly build? [y/N]: "
    read -r answer_nightly
    if [ "$answer_nightly" = "y" ] || [ "$answer_nightly" = "Y" ]; then
        nightly=1
    fi
fi

if [ "$debug" -eq 0 ] && [ "$have_term" -eq 1 ]; then
    printf "do you want to install a debug build? [y/N]: "
    read -r answer_debug
    if [ "$answer_debug" = "y" ] || [ "$answer_debug" = "Y" ]; then
        debug=1
    fi
fi

if [ "$verify" -eq 0 ] && [ "$have_term" -eq 1 ]; then
    printf "do you want to download and verify the gpg signature? [y/N]: "
    read -r answer_verify
    if [ "$answer_verify" = "y" ] || [ "$answer_verify" = "Y" ]; then
        verify=1
    fi
fi

if [ ! "$(readlink "$install_dir/f")" = "$install_dir/flow" ]; then
    if [ "$have_term" -eq 1 ] && [ "$add_alias" -eq 0 ]; then
        printf "do you want to create an alias 'f' for 'flow'? [y/N]: "
        read -r answer_alias
        if [ "$answer_alias" = "y" ] || [ "$answer_alias" = "Y" ]; then
            add_alias=1
        fi
    fi
fi

if [ "$nightly" -eq 1 ]; then
    repo="neurocyte/flow-nightly"
    title="flow nightly build"
else
    repo="neurocyte/flow"
    title="flow"
fi

# detect os and architecture
os="$(uname -s | tr '[:upper:]' '[:lower:]')"
if [ "$os" = "darwin" ]; then
    os="macos"
fi

arch="$(uname -m)"
case "$arch" in
x86_64) arch="x86_64" ;;
arm64) arch="aarch64" ;;
i686) arch="x86" ;;
i386) arch="x86" ;;
esac

# get latest version tag from github releases api
version=$(curl -s "https://api.github.com/repos/$repo/releases/latest" | grep '"tag_name":' | cut -d'"' -f4)
[ -z "$version" ] && {
    echo "failed to fetch $title latest version"
    exit 1
}
title="$title $version"

if [ "$debug" -eq 1 ]; then
    title="$title (debug)"
fi

if [ "$force_update" -eq 0 ] && [ -e "$install_dir/flow" ]; then
    current_version=$(flow --version 2>/dev/null | grep version: | cut -f2 -d ' ')
    if [ "$current_version" = "$version" ]; then
        echo "flow is up-to-date (version $version @ $install_dir/flow)"
        exit 0
    else
        if [ -n "$current_version" ]; then
            echo "updating flow from $current_version to $version"
        fi
    fi
fi

if [ "$use_sudo" -eq 0 ] && [ -n "$need_sudo" ]; then
    printf "%s is not writable. Permissions will be requested with sudo.\n" "$need_sudo"
    use_sudo=1
fi

SUDOCMD=""
if [ -n "$need_sudo" ]; then
    if [ "$use_sudo" -eq 1 ]; then
        SUDOCMD=sudo
    else
        echo "error: '$need_sudo' is not writable."
        exit 1
    fi
fi

# construct download url
# note: nightly assets are named like "flow-<version>-<os>-<arch>.<ext>"
filename="flow-$version-$os-$arch"
ext="tar.gz"
if [ "$os" = "windows" ]; then
    ext="zip"
fi
if [ "$debug" -eq 1 ]; then
    filename="$filename-debug"
fi
url="https://github.com/$repo/releases/download/$version/$filename.$ext"

echo "downloading $title..."

curl -fL "$url" -o "$tmp_path/$filename.$ext"

# simple file size check (adjust threshold if needed)
filesize=$(stat -c%s "$tmp_path/$filename.$ext" 2>/dev/null || stat -f%z "$tmp_path/$filename.$ext")
if [ "$filesize" -lt 16384 ]; then
    echo "downloaded file appears to be invalid (size: ${filesize} bytes)"
    exit 1
fi

if [ "$verify" -eq 1 ]; then
    curl -fL "$url.sig" -o "$tmp_path/$filename.$ext.sig"
    curl -fL 'https://flow-control.dev/public.gpg' -o "$tmp_path/flow-control-public.gpg"
    gpg --no-default-keyring --keyring "$tmp_path/flow-control-public.gpg" --verify "$tmp_path/$filename.$ext.sig" "$tmp_path/$filename.$ext"

    if [ "$local" -eq 1 ]; then
        gpg --verify "$tmp_path/$filename.$ext.sig" "$tmp_path/$filename.$ext"
    fi

    rm "$tmp_path/flow-control-public.gpg"
    rm "$tmp_path/$filename.$ext.sig"
fi

echo "installing $title to $install_dir/flow..."
if [ "$ext" = "tar.gz" ]; then
    $SUDOCMD tar -xzf "$tmp_path/$filename.$ext" -C "$install_dir"
else
    $SUDOCMD unzip -o "$tmp_path/$filename.$ext" -d "$install_dir"
fi

$SUDOCMD chmod +x "$install_dir/flow"
rm "$tmp_path/$filename.$ext"

if [ "$add_alias" -eq 1 ]; then
    if [ "$(readlink "$install_dir/f")" = "$install_dir/flow" ]; then
        echo "alias $install_dir/f -> $install_dir/flow already exists"
    else
        if [ -e "$install_dir/f" ]; then
            echo "WARNING: existing file or alias detected at $install_dir/f, skipping alias creation..."
        else
            $SUDOCMD ln -s "$install_dir/flow" "$install_dir/f"
            echo "alias $install_dir/f -> $install_dir/flow created successfully"
        fi
    fi
fi

echo "$title installed successfully to $install_dir/flow"
