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

cd "$(dirname "$(readlink -f "$BASH_SOURCE")")"

versions=( "$@" )
if [ ${#versions[@]} -eq 0 ]; then
	versions=( */ )
	json='{}'
else
	json="$(< versions.json)"
fi
versions=( "${versions[@]%/}" )

tmp="$(mktemp -d)"
rmTmp="$(printf 'rm -rf %q' "$tmp")"
trap "$rmTmp" EXIT

_get() {
	local url="$1"; shift
	local file="${url////_}"
	file="${file//%/_}"
	file="${file//+/_}"
	file="${file//:/_}"
	file="$tmp/$file"
	if [ ! -s "$file" ]; then
		curl -fsSL "$url" -o "$file" --retry 5 || return 1
	fi
	if [ "$#" -gt 0 ]; then
		grep "$@" "$file"
	else
		cat "$file"
	fi
}

abs-url() {
	local url="$1"; shift
	local base="$1"; shift

	case "$url" in
		http://* | https://* ) ;;

		/*)
			local extra="${base#*://*/}"
			local baseBase="${base%$extra}"
			baseBase="${baseBase%/}"
			url="$baseBase$url"
			;;

		*)
			echo >&2 "error: TODO parse '$url' relative to '$base'"
			exit 1
			;;
	esac

	echo "$url"
}

jdk-java-net-download-url() {
	local javaVersion="$1"; shift
	local fileSuffix="$1"; shift
	_get "https://jdk.java.net/$javaVersion/" \
		-Eom1 "https://download.java.net/[^\"]+$fileSuffix"
}

jdk-java-net-download-version() {
	local javaVersion="$1"; shift
	local downloadUrl="$1"; shift

	downloadVersion="$(grep -Eom1 "openjdk-$javaVersion[^_]*_" <<<"$downloadUrl")" || return 1
	downloadVersion="${downloadVersion%_}"
	downloadVersion="${downloadVersion#openjdk-}"

	echo "$downloadVersion"
}

# see https://stackoverflow.com/a/2705678/433558
sed_escape_rhs() {
	sed -e 's/[\/&]/\\&/g' <<<"$*" | sed -e ':a;N;$!ba;s/\n/\\n/g'
}
sed_s() {
	local lhs="$1"; shift
	local rhs="$1"; shift
	rhs="$(sed_escape_rhs "$rhs")"
	echo -n "s/$lhs/$rhs/g"
}
sed_s_pre() {
	local lhs="$1"; shift
	local rhs="$1"; shift
	rhs="$(sed_escape_rhs "$rhs")"
	echo -n "s/^($lhs) .*$/\1 $rhs/"
}

for version in "${versions[@]}"; do
	export version
	doc='{}'
	possibleArches=(
		# https://jdk.java.net/26/
		'linux-aarch64'
		'linux-x64'
		'linux-x64-musl'
		'windows-x64'
	)
	for arch in "${possibleArches[@]}"; do
		downloadSuffix="_${arch}_bin"
		case "$arch" in
			linux-*) downloadSuffix+='.tar.gz'; bashbrewArch= ;;
			windows-*) downloadSuffix+='.zip'; bashbrewArch='windows-' ;;
			*) echo >&2 "error: unknown Oracle arch: '$arch'"; exit 1 ;;
		esac
		jqExprPrefix=
		if [[ "$arch" == *-musl ]]; then
			jqExprPrefix='.alpine'
		fi
		if downloadUrl="$(jdk-java-net-download-url "$version" "$downloadSuffix")" \
			&& [ -n "$downloadUrl" ] \
			&& downloadSha256="$(_get "$downloadUrl.sha256")" \
			&& [ -n "$downloadSha256" ] \
		; then
			downloadVersion="$(jdk-java-net-download-version "$version" "$downloadUrl")"
			currentVersion="$(jq <<<"$doc" -r "$jqExprPrefix.version // \"\"")"
			if [ -n "$currentVersion" ] && [ "$currentVersion" != "$downloadVersion" ]; then
				echo >&2 "error: Oracle version mismatch: '$currentVersion' vs '$downloadVersion'"
				exit 1
			elif [ -z "$currentVersion" ]; then
				echo "$version: $downloadVersion${jqExprPrefix:+ (alpine)}"
			fi
			case "$arch" in
				*-aarch64*) bashbrewArch+='arm64v8' ;;
				*-x64*) bashbrewArch+='amd64' ;;
				*) echo >&2 "error: unknown Oracle arch: '$arch'"; exit 1 ;;
			esac
			export arch bashbrewArch downloadUrl downloadSha256 downloadVersion
			doc="$(jq <<<"$doc" -c '
				'"$jqExprPrefix"'.version = env.downloadVersion
				| '"$jqExprPrefix"'.jdk.arches[env.bashbrewArch] = {
					url: env.downloadUrl,
					sha256: env.downloadSha256,
				}
			')"
		fi
	done

	if ! jq <<<"$doc" -e '[ .. | objects | select(has("arches")) | .arches | has("amd64") ] | all' &> /dev/null; then
		echo >&2 "error: missing 'amd64' for '$version'; cowardly refusing to continue! (because this is almost always a scraping flake or similar bug)"
		exit 1
	fi

	json="$(jq <<<"$json" -c --argjson doc "$doc" '
		.[env.version] = $doc + {
			variants: [
				(
					"9",
					"8",
					empty
				| "oraclelinux" + .),
				(
					"trixie",
					"bookworm",
					empty
				| ., "slim-" + .),
				if $doc.alpine then
					"3.22",
					"3.21",
					empty
				| "alpine" + . else empty end,
				if $doc.jdk.arches | keys | any(startswith("windows-")) then
					(
						"ltsc2025",
						"ltsc2022",
						empty
					| "windows/windowsservercore-" + .),
					(
						"ltsc2025",
						"ltsc2022",
						empty
					| "windows/nanoserver-" + .)
				else empty end
			],
		}
	')"
done

jq <<<"$json" -S . > versions.json
