#!/bin/dash
# getjava rev. [2]
# ^ keep that line as is for the updater, only increase the revision number
#
# jamesbond 2015, 2019, 2021, 2022
# JakeSFR 2018, 2019, 2020, 2021
# MIT license

# We support only the latest version
# For previous versions please visit adoptium.net and download yourself.

APPTITLE="Download Java SDK SFS"

UPDATE_URL='http://distro.ibiblio.org/fatdog/other/getjava.sh'
MYPATH="$(readlink -f "$0")"
WORKDIR="/tmp/getjava.$$"

#COMP_MODE="-comp lzo -Xcompression-level 1"
COMP_MODE=${COMP_MODE:-"-comp xz -Xbcj x86"}

API=https://api.adoptium.net
#API_CALLER=curl # this has problem resolving adoptium.net DNS name
API_CALLER="wget -qO - "



########## Adoptium API stuff ###########

# $1-method, $2 ... parameters
# output: URL
construct_url() {
	URL="$API$1"
	local params=
	shift
	while [ "$1" ]; do
		params="$params&$1"
		shift
	done
	[ "$params" ] && URL="$URL?$params"
}

# $1-method, $2 ... parameters
api_call() {
	construct_url "$@"
	echo "$URL"
	$API_CALLER "$URL"
}

# $1-fn $2-URL $3... param
api_file_download() {
	local fn="$1"
	shift
	construct_url "$@"
	wget -O "$fn" "$URL"
}

filter_releases() {
	sed -n '/"available_releases"/,/\]/ {/avail/d; /\]/d; s/,//; p }' 
}

filter_relname() {
	 sed -n '/"release_name":/ {s/.*": "//;s/".*//p}'
}

filter_dl_link() {
	 sed -n '/"link":/ {s/.*http/http/;s/".*//p}'
}

filter_checksum() {
	 sed -n '/"checksum"/ {s/.*": "//;s/",*//p};'
}


########## UI helpers #########

# $1-info
msgbox() {
	if [ $DISPLAY ]; then
		Xdialog --title "$APPTITLE" --msgbox "$1" 0 0 10000
	else
		dialog --backtitle "$APPTITLE" --msgbox "$1" 0 0 > /dev/stderr
	fi
}

# $1-info $2-timeout (in ms)
infobox() {
	local timeout=${2:-10000}
	if [ $DISPLAY ]; then
		Xdialog --title "$APPTITLE" --infobox "$1" 0 0 $timeout
	else
		dialog --backtitle "$APPTITLE" --no-cancel --pause "$1" 12 60 $(( timeout/1000 )) > /dev/stderr
	fi
}

# $1-text, $2-choices, output: stdout
choices() {
	if [ $DISPLAY ]; then
		eval Xdialog --title \"$APPTITLE\" --stdout --no-tags --menubox \""$1"\" 20 100 5 $2
	else 
		eval dialog --backtitle \"$APPTITLE\" --stdout --no-tags --menu \""$1"\" 0 0 0 $2
	fi
}

# $1-text, $2-choices, output: stdout
multi_choices() {
	if [ $DISPLAY ]; then
		eval Xdialog --title \"$APPTITLE\" --stdout --no-tags --separator \" \" --checklist \""$1"\" 20 100 5 $2
	else
		eval dialog --title \"$APPTITLE\" --stdout --no-tags --separator \" \" --checklist \""$1"\" 0 0 0 $2
	fi
}

# $1-text
yesno() {
	if [ $DISPLAY ]; then
		Xdialog --title "$APPTITLE" --yesno "$1" 0 0
	else
		dialog --title "$APPTITLE" --yesno "$1" 0 0
	fi
}

# $1-prompt, $2-current value
inputbox() {
	if [ $DISPLAY ]; then
		Xdialog --title "$APPTITLE" --stdout --inputbox "$1" 0 0 "$2"
	else
		dialog --title "$APPTITLE" --stdout --inputbox "$1" 0 0 "$2"		
	fi
}

# $1-prompt
fselect() {
	if [ $DISPLAY ]; then
		Xdialog --title "$APPTITLE" --backtitle "$1" --stdout --no-buttons --fselect "$PWD" 0 0
	else
		dialog --title "$APPTITLE" --backtitle "$1" --stdout --fselect "$PWD"/ 10 70
	fi
}

# $1-prompt
tailbox() {
	local tmpfile=/tmp/bt-status.$$
	if [ $DISPLAY ]; then
		Xdialog --title "$APPTITLE" --no-cancel --backtitle "$1" --tailbox - 0 0
	else
		cat > $tmpfile
		dialog --title "$APPTITLE" --backtitle "$1" --textbox $tmpfile 0 0
		rm $tmpfile
	fi
}

# $1-text
splash() {
	if [ "$XPID" ]; then
		kill $XPID
		XPID=
	fi

	if [ "$1" ]; then	
		if [ $DISPLAY ]; then
			Xdialog --title "$APPTITLE" --no-buttons --infobox "$1" 0 0 1000000 &
			XPID=$!
		else
			dialog --backtitle "$APPTITLE" --infobox "$1" 0 0 > /dev/stderr
		fi
	fi
}

# $1-text
die() {
	infobox "$1"
	exit
}

# $1-option, $* options
has_option() {
	local p inp=$1
	shift
	for p; do
		case $p in
			$inp) return 0
		esac	
	done
	return 1
}


########## handlers ###########

check_root() {
	if [ $(id -u) -ne 0 ]; then
		infobox "Must run as root" 10000
		exit 1
	fi
}

# Update itself
update_self() {
	local oldrev newrev tmpdl='getjava.sh.tmp'

	echo "Updating..."

	if curl -f -R -k -s "$UPDATE_URL" -o "$tmpdl"; then
		# get revisions
		oldrev="$(sed -n 's/# getjava.*\[\([0-9]\+\)\].*/\1/p;' "$MYPATH" | head -n 1)"
		newrev="$(sed -n 's/# getjava.*\[\([0-9]\+\)\].*/\1/p;' "$tmpdl" | head -n 1)"

		if [ "$oldrev" -a "$newrev" ] && [ $newrev -gt $oldrev ]; then
			mv "$tmpdl" "$MYPATH"
			chmod +x "$MYPATH"
			echo "Successfully updated to revision [${newrev}]."
		else
			echo "The latest revision [${oldrev}] is already installed."
		fi

	else
		echo "Update failed!"
	fi
}

download() {
	DL_URL= DL_CHECKSUM= DL_FB=
	if releases=$(api_call /v3/info/available_releases | filter_releases); then
		RELS=
		for p in $releases; do
			RELS="$RELS $p $p"
		done
		#echo $RELS
		if REL=$(choices "Choose the Java API you want to download" "$RELS"); then
			if INFO=$(api_call /v3/assets/latest/$REL/hotspot os=linux architecture=x64 image_type=jdk clib=glibc); then
				#echo "$INFO"
				RELNAME=$(echo "$INFO" | filter_relname) ### used by makesfs
				if yesno "Found\n\n$RELNAME release\n\nfor Java API $REL.\n\nDownload?\n"; then
					DL_URL=$(echo "$INFO" | filter_dl_link)
					DL_CHECKSUM=$(echo "$INFO" | filter_checksum)
					DL_FN=${DL_URL##*/} ### used by makesfs
					splash "Downloading $DL_FN\n\nPlease wait ...\n\n" 
					wget -O "$DL_FN" "$DL_URL"
					if [ $(sha256sum "$DL_FN" | sed 's/ .*//') != "$DL_CHECKSUM" ]; then
						splash
						infobox "Download failed. Exiting." 10000
						exit 2
					else
						return	# everything went well
					fi
				fi
			fi
		fi
	fi

	exit 1	# something went wrong or user cancelled the program
}

makesfs() {
	splash "Converting to SFS.\n\nPlease wait ...\n\n"
	local FULL_VERSION=$(echo $RELNAME | sed 's/jdk[-]*//')

	cd $WORKDIR &&
	mkdir -p workroot && cd workroot &&
	tar -xf ../"$DL_FN" && rm -f ../"$DL_FN" &&

	mkdir -p ./opt ./usr/bin &&
	mv ./jdk* ./opt/java-$FULL_VERSION &&
	ln -sf java-$FULL_VERSION ./opt/java &&
	
	# create a wrapper that extends LD_LIBRARY_PATH (req. for JDK 15+)
	cat << "EOF" > ./usr/bin/jdk_wrapper
#!/bin/sh

LD_LIBRARY_PATH="/opt/java/lib:$LD_LIBRARY_PATH"	# the order matters!
exec /opt/java/bin/${0##*/} "$@"
EOF
	chmod +x ./usr/bin/jdk_wrapper
	
	# create symlinks to a wrapper
	for p in jar jarsigner java javac javadoc javah javap javaws jconsole jvisualvm policytool keytool; do
		[ -e ./opt/java/bin/$p ] && ln -sf jdk_wrapper ./usr/bin/$p
	done && 
	
	cd .. &&
	mksquashfs workroot $HOME/java-jdk-$FULL_VERSION-x64.sfs -noappend $COMP_MODE &&
	rm -rf workroot
	splash
}




### main
check_root "$@"

trap '[ -e $WORKDIR ] && cd $WORKDIR && cd .. && rm -r $WORKDIR; exit' INT HUP 0
mkdir -p $WORKDIR; cd $WORKDIR

case "$1" in
	"")
		download
		makesfs
		infobox "Done - SFS saved to $HOME" 10000
		;;
				
	-U|--update)
		update_self
		;;

	-h|--help|*)
		cat << EOF
${0##/*} [--noprompt] [-U|--update]

A simple script to download the latest version of Java and turn it
into an SFS. The Java binary is from Eclipse Temurin / Adoptium Project.

-U or --update to update the script with the latest version.

EOF
		;;
esac
