#!/usr/bin/env bash
set -e

# Switch between git worktrees with speed.

args=("$@")
VERSION="0.2.4-fork"
TMP_PATH=$(mktemp)
BINARY_PATH=$(realpath "$0")
VERSION_CACHE_FILE=${XDG_CACHE_HOME:-$HOME/.cache}/wt_latest_update_check.json
JQ_URL="https://stedolan.github.io/jq/download"
RELEASE_URL="https://github.com/mateusauler/git-worktree-switcher/releases/latest"
RELEASE_API_URL="https://api.github.com/repos/mateusauler/git-worktree-switcher/releases/latest"
CHANGE_DIRECTORY_PREFIX="changedir:"


# Escape forward slash
arg=${args[0]/\//\\\/}

worktree_list_names() {
	git worktree list --porcelain 2> /dev/null | sed -n 's/^worktree\s*//p' | xargs -r -I{} basename {}
}

help_message() {
	echo -e "wt lets you switch between your git worktrees with speed.\n"
	echo "Usage:"
	echo -e "\twt: go to the main worktree"
	echo -e "\twt <worktree-name>: search for worktree names and change to that directory."
	echo -e "\twt names: list out only the git worktree names."
	echo -e "\twt update: update to the latest release of worktree switcher."
	echo -e "\twt version: show the CLI version."
	echo -e "\twt init <shell>: print the init script for <shell>."
	echo -e "\twt help: shows this help message."
}

download_latest_update() {
	download_url=$(curl -sL $RELEASE_API_URL | jq -r '.assets[0].browser_download_url')

	echo "Downloading latest version $fetched_tag_name"
	curl -sL -o "$TMP_PATH" "$download_url"

	echo "Updating to latest version..."
	chmod +x "$TMP_PATH"
	sudo mv "$TMP_PATH" "$BINARY_PATH"
	rm -f "$TMP_PATH"

	echo "You are using the latest version of worktree switcher: $fetched_tag_name"
}

check_release_version() {
	fetched_tag_name=$(check_and_cache_update)

	if [ "$fetched_tag_name" == $VERSION ]; then
		echo "You have the latest version of worktree switcher!"
		echo "Version: $VERSION"
	else
		download_latest_update
	fi
}

update() {
	if [ -z "$(command -v jq)" ]; then
		echo "jq is required for updating worktree switcher via this command."
		echo -e "Install jq:\n$JQ_URL.\n"
		echo -e "Or visit:\n$RELEASE_URL"
	else
		check_release_version
	fi
}

auto_check_update() {
	show_updates() {
		if [[ "$1" != "$VERSION" ]]; then
			echo "Version $1 available! Run 'wt update' to update." 1>&2
			echo "Currently running version $VERSION." 1>&2
		fi
	}

	if [[ -f "$VERSION_CACHE_FILE" ]]; then
		check_timestamp=$(jq -r '.timestamp' < "$VERSION_CACHE_FILE")
		latest_known_version=$(jq -r '.version' < "$VERSION_CACHE_FILE")
		one_day_ago_epoch=$(date -d '1 days ago' +%s)

		if (( check_timestamp > one_day_ago_epoch )); then
			show_updates "$latest_known_version"
			return 0
		fi
	fi

	fetched_tag_name=$(check_and_cache_update)
	show_updates "$fetched_tag_name"
}

check_and_cache_update() {
	echo "Checking for updates..." 1>&2
	fetched_tag_name=$(curl -sL $RELEASE_API_URL | jq -r '.tag_name')

	echo "$fetched_tag_name"

	mkdir -p "$(dirname "$VERSION_CACHE_FILE")"
cat > "$VERSION_CACHE_FILE" <<EOF
{
	"timestamp": "$(date +%s)",
	"version": "$fetched_tag_name"
}
EOF
}

get_dest_path="\$(echo \"\$result\" | awk '/^$CHANGE_DIRECTORY_PREFIX.*/ {sub(\"$CHANGE_DIRECTORY_PREFIX\", \"\"); print; exit}')"

init_bash() {
	cat <<EOF
wt() {
	result="\$($BINARY_PATH "\$@")"
	dest_path="$get_dest_path"

	if [[ -n "\$dest_path" ]]; then
		cd "\$dest_path" || return
	elif [[ -n \$result ]]; then
		echo "\$result"
	fi
}
EOF
}

init_fish() {
	cat <<EOF
function wt
	set -l result "\$($BINARY_PATH \$argv)"
	set -l dest_path "$get_dest_path"

	if test -n "\$dest_path"
		cd "\$dest_path"
	else if test -n "\$result"
		echo "\$result"
	end
end
EOF
}

init() {
	shell="${args[1]}"
	if [[ -z $shell ]]; then
		echo "Please supply a shell."
		echo "    eg. wt init bash"
		exit 1
	fi
	case "$shell" in
	bash|zsh)
		init_bash
		;;
	fish)
		init_fish
		;;
	*)
		echo "Unsupported shell: $shell"
		exit 1
		;;
	esac
}

case "${args[0]}" in
names)
	worktree_list_names
	;;
update)
	update
	;;
help)
	help_message
	;;
version)
	echo Version: $VERSION
	;;
init)
	init
	;;
*)
	auto_check_update
	directory=$(git worktree list --porcelain 2> /dev/null | sed -n '/'"${arg:-.}"'/{s/^worktree\s*//p;q}')
	;;
esac

# If directory variable is not empty then change worktree
if [ -z "$directory" ]; then
	:
else
	echo "$CHANGE_DIRECTORY_PREFIX$directory"
fi
