#!/bin/bash

# This script is used to check if given package can be auto-updated and optionally enable if it can be.
# NOTE: You should not trust this script if package uses commit hashes for versioning(eg. 'tsu') or
# TERMUX_PKG_VERSION is defined by us and not upstream(i.e we use some arbitrary version. For eg. when only
# getting source files based on commit hash).

# The MIT License (MIT)

# Copyright (c) 2022 Aditya Alok <dev.aditya.alok+legal@gmail.com>

# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:

# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.

# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

set -e

TERMUX_SCRIPTDIR="$(realpath "$(dirname "$(readlink -f "$0")")/../..")"
declare -a UNIQUE_PACKAGES

_RESET_COLOR="\033[0m"
_BLUE="\033[1;34m"
_GREEN="\033[0;32m"
_RED="\033[0;31m"
_YELLOW="\033[0;33m"
_TEAL="\033[0;36m"

warn() {
	[[ "${SILENT}" == "true" ]] && return
	local warn_color="\033[1;33m"
	echo -e "${_BLUE}[${warn_color}*${_BLUE}]${_YELLOW} $*${_RESET_COLOR}" >&2
}

error() {
	[[ "${SILENT}" == "true" ]] && exit 1
	local error_color="\033[1;31m"
	echo -e "${_BLUE}[${error_color}!${_BLUE}]${_RED} $*${_RESET_COLOR}" >&2
	exit 1
}

info() {
	[[ "${SILENT}" == "true" ]] && return
	local info_color="\033[1;32m"
	echo -e "${_BLUE}[${info_color}+${_BLUE}]${_TEAL} $*${_RESET_COLOR}"
}

usage() {
	echo -e "${_BLUE}Usage:${_RESET_COLOR} $(basename "$0")" \
		"${_GREEN}[-h|--help]${_RESET_COLOR}" \
		"${_GREEN}[-s|--silent]${_RESET_COLOR}" \
		"${_GREEN}[--enable]${_RESET_COLOR}" \
		"${_GREEN}PACKAGE [PACKAGE...]${_RESET_COLOR}"
	echo
	echo -e "${_TEAL}Check if packages can be auto-updated and optionally enable if so.${_RESET_COLOR}"
	echo
	echo -e "${_RED}NOTE: ${_YELLOW}You should not trust this script if\n" \
		"\t${_BLUE}- ${_YELLOW}package uses commit hashes for versioning (eg. 'tsu') or\n" \
		"\t${_BLUE}- ${_GREEN}TERMUX_PKG_VERSION ${_YELLOW}is defined by us and not upstream, i.e we use some arbitrary version.\n" \
		"\t  For eg. when only getting source files based on commit hash."
	echo
	echo -e "${_BLUE}Options:${_RESET_COLOR}"
	echo -e "${_GREEN}-h --help${_TEAL} Show this help message.${_RESET_COLOR}"
	echo -e "${_GREEN}--enable${_TEAL} Enable auto-updates for packages if it can be." \
		"Writes ${_YELLOW}TERMUX_PKG_AUTO_UPDATE=true${_TEAL} to build.sh${_RESET_COLOR}"
}

can_be_updated_from_github() {
	local url="$1"
	if grep -Eq "^https?://github.com" <<<"$url"; then
		local stderr
		stderr="$(
			set -euo pipefail
			. "${TERMUX_SCRIPTDIR}/scripts/updates/api/termux_github_api_get_tag.sh"
			. "${TERMUX_SCRIPTDIR}/scripts/updates/utils/termux_error_exit.sh"
			termux_github_api_get_tag "$url" 2>&1 >/dev/null
		)" || {
			if grep -q "HTTP code:" <<<"${stderr}"; then
				local http_code
				http_code="$(grep "HTTP code:" <<<"${stderr}" | cut -d ':' -f 2 | tr -d ' ')"
				if [[ "$http_code" == "000" ]]; then
					error "Could not connect to GitHub API. Please check your internet connection."
				fi
				warn "Failed to get tag from github api [HTTP code: $http_code]."
				return 1
			elif grep -q "ERROR:" <<<"${stderr}"; then
				error "$(grep "ERROR:" <<<"${stderr}" | cut -d ':' -f 2 | sed 's/^[[:space:]]*//')"
				return 1
			fi
		}
		return 0
	else
		warn "Not a github url: $url"
		return 1
	fi
}

can_be_updated_from_gitlab() {
	local url="$1"
	if grep -Eq "^https?://gitlab.com" <<<"$url"; then
		stderr="$(
			set -euo pipefail
			. "${TERMUX_SCRIPTDIR}/scripts/updates/api/termux_gitlab_api_get_tag.sh"
			. "${TERMUX_SCRIPTDIR}/scripts/updates/utils/termux_error_exit.sh"
			termux_gitlab_api_get_tag "$url" 2>&1 >/dev/null
		)" || {
			if grep -q "HTTP code:" <<<"${stderr}"; then
				local http_code
				http_code="$(grep "HTTP code:" <<<"${stderr}" | cut -d ':' -f 2 | tr -d ' ')"
				if [[ "$http_code" == "000" ]]; then
					error "Could not connect to GitLab API. Please check your internet connection."
				fi
				warn "Failed to get tag from gitlab api [HTTP code: $http_code]."
				return 1
			elif grep -q "ERROR:" <<<"${stderr}"; then
				warn "$(grep "ERROR:" <<<"${stderr}" | cut -d ':' -f 2 | sed 's/^[[:space:]]*//')"
				return 1
			fi
		}
		return 0
	else
		warn "Not a gitlab url: $url"
		return 1
	fi
}

is_unique_package() {
	local package="$1"
	if [[ -z "${UNIQUE_PACKAGES[1]}" ]]; then
		# NOTE: mapfile requires bash 4+
		mapfile -t UNIQUE_PACKAGES < <(
			curl --silent --location --retry 5 --retry-delay 5 --retry-max-time 60 \
				"https://repology.org/api/v1/projects/?inrepo=termux&&repos=1" |
				jq -r 'keys[]'
		)

		[[ -z "${UNIQUE_PACKAGES[1]}" ]] && error "Failed to get unique packages from repology.org"
	fi
	# shellcheck disable=SC2076
	if [[ ! " ${UNIQUE_PACKAGES[*]} " =~ " ${package} " ]]; then
		return 0 # Package is not unique, hence can be updated.
	else
		error "Package '$package' is unique, hence cannot be auto-updated."
	fi
}

write_to_first_empty_line() {
	local -r file="$1"
	local -r line="$2"

	if ! grep -q "^$line$" "$file"; then
		# Find first empty line from top of file:
		local -r first_empty_line=$(sed -n '/^$/=' "$file" | head -n 1)
		sed -i "${first_empty_line}i$line" "$file"
	else
		warn "$line already exists in $(basename "$file"). Skipping."
	fi
}

check() {
	PKG_NAME="$1"
	[[ "${SILENT}" == "true" ]] || echo -e "${_BLUE}==>${_YELLOW} ${PKG_NAME}${_RESET_COLOR}"
	SRC_URL="$(
		# shellcheck source=/dev/null
		. "${TERMUX_SCRIPTDIR}"/packages/"${PKG_NAME}"/build.sh >/dev/null 2>&1
		echo "${TERMUX_PKG_SRCURL}"
	)"

	if [[ -z "${SRC_URL}" ]]; then
		error "Could not find TERMUX_PKG_SRCURL."
	fi

	checks=(
		"can_be_updated_from_github"
		"can_be_updated_from_gitlab"
		"is_unique_package"
	)
	can_be_updated=false
	for check in "${checks[@]}"; do
		info "Checking if package ${check//_/ }..."
		if $check "${SRC_URL}"; then
			can_be_updated=true
			break
		fi
	done

	if [[ "${can_be_updated}" == "true" ]]; then
		info "Package can be auto-updated."
		if [[ "${ENABLE}" == "--enable" ]]; then
			info "Enabling auto-update..."
			write_to_first_empty_line \
				"${TERMUX_SCRIPTDIR}/packages/${PKG_NAME}/build.sh" "TERMUX_PKG_AUTO_UPDATE=true"
			info "Done."
			return
		fi
	else
		error "Package cannot be auto-updated."
	fi
}

if [[ $# -lt 1 ]] || [[ $# -gt 2 ]]; then
	error "Invalid number of arguments. See --help for usage."
fi

while [[ $# -gt 0 ]]; do
	case "$1" in
	--enable)
		ENABLE="--enable"
		;;
	-s | --silent)
		SILENT=true
		;;
	-h | --help)
		usage
		;;
	*)
		check "$1"
		[[ "${SILENT}" == "true" ]] || echo # Newline.
		;;
	esac
	shift
done
