#!/bin/bash

# Exits the whole script, if an error (exit code >0) occur.
set -e

STEAM_PROTON_DIR="$HOME/.local/share/Steam/compatibilitytools.d"
LUTRIS_WINE_DIR="$HOME/.local/share/lutris/runners/wine"
LUTRIS_PROTON_DIR="$HOME/.local/share/lutris/runners/proton"
LUTRIS_DXVK_DIR="$HOME/.local/share/lutris/runtime/dxvk"
LUTRIS_VKD3D_PROTON_DIR="$HOME/.local/share/lutris/runtime/vkd3d"
LUTRIS_DXVK_NVAPI_DIR="$HOME/.local/share/lutris/runtime/dxvk-nvapi"

# Function for download the archive from the passed url in a temporary directory, then extract in the passed directory. Checks, which archive format is used.
download_and_extract() {
	local url=$1
	local output_dir=$2
	local tmp_dir
	tmp_dir=$(mktemp -d)
	echo
	echo "Lade herunter: $url"
	wget -q --show-progress -P "$tmp_dir" "$url"
	echo
	echo "Entpacke nach: $output_dir"
	archive=$(find "$tmp_dir" -type f)
	mkdir -p "$output_dir"
	if [[ "$archive" == *.tar.gz ]]; then
		tar --gzip -xf "$archive" -C "$output_dir"
        elif [[ "$archive" == *.tar.xz ]]; then
		tar --xz -xf "$archive" -C "$output_dir"
	elif [[ "$archive" == *.tar.zst ]]; then
		tar --zstd -xf "$archive" -C "$output_dir"
        else
		echo "Unbekanntes Archivformat: $archive"
		exit 1
	fi
	rm -rf "$tmp_dir"
}

# Compare two passed version numbers, against (less than, equal or greater than) and store the result in a variable.
version_compare() {
    if [[ "$1" == "$2" ]]; then # installed version = latest version.
        result_compare=0
    elif [[ "$(printf '%s\n' "$1" "$2" | sort -V | tail -n 1)" == "$1" ]]; then # installed version > latest version.
        result_compare=1
    else # installed version < latest version.
        result_compare=2
    fi
}

# Checks if 'jq' (Command-line JSON processor) package is installed, otherwise the script exits with error code 1.
if ! command -v jq &> /dev/null; then
	echo "Fehler: jq ist nicht installiert. Bitte installiere es mit 'sudo apt install jq' (Debian-/Ubuntu-basierte Systeme),"
	echo "'sudo dnf install jq' (Fedora-basierte Systeme) oder 'sudo pacman -S jq' (Arch-basierte Systeme) und führe das Skript"
	echo "nocheinmal aus."
	exit 1
fi

###################################
# GE-Proton Update (Steam) prüfen #
###################################

process_ge_proton_in_steam() {
	download_and_extract "$ge_proton_asset_url" "$STEAM_PROTON_DIR"
	sed -i -e 's/GE-Proton/GE-Proton /g' "$STEAM_PROTON_DIR"/GE-Proton"$latest_ge_proton_version"/compatibilitytool.vdf # Replace two 'GE-Proton' strings in file with an additional space character 'GE-Proton ' to display version clearer in Steam, e.g. 'GE-Proton10-10' --> 'GE-Proton 10-10'.
	mv "$STEAM_PROTON_DIR"/GE-Proton"$latest_ge_proton_version" "$STEAM_PROTON_DIR/GE-Proton $latest_ge_proton_version" # Rename the directory, that contains GE-Proton to display version clearer in Lutris, similar to above.
	echo "Erledigt."
	echo "Lösche altes GE-Proton-Verzeichnis..."
	rm -rf "$STEAM_PROTON_DIR/GE-Proton $installed_ge_proton_version"
	echo "Erledigt."
}

echo "========== Steam: GE-Proton =========="
echo "Prüfe auf eine neue Version von GE-Proton..."

latest_ge_proton_version=$(curl -s https://api.github.com/repos/GloriousEggroll/proton-ge-custom/releases/latest | jq -r .tag_name | cut -c 10-14)
ge_proton_asset_url=$(curl -s https://api.github.com/repos/GloriousEggroll/proton-ge-custom/releases/latest | jq -r '.assets[] | select(.name | endswith(".tar.gz")) | .browser_download_url')
ge_proton_dir=("$STEAM_PROTON_DIR/GE-Proton "*-*)  # Find the existing Proton-GE directory with the version number in it's name. Is needed because globbing is not allowed in IF statement.

if [[ -d "${ge_proton_dir[0]}" ]] > /dev/null; then
	installed_ge_proton_version=$(cut -c 21-25 "${ge_proton_dir[0]}/version" 2> /dev/null)
	if [[ "$latest_ge_proton_version" -gt "$installed_ge_proton_version" ]]; then
		echo "Warnung: Die vorhandene Version von GE-Proton ist neuer als die aktuellste Version im Github-Repository!"
		echo "$installed_ge_proton_version"" --> ""$latest_ge_proton_version"" (Downgrade!)"
		echo ""
		ask_downgrade_ge_proton() {
		read -r -p "Möchtest du ein Downgrade zulassen? (j/N): " User_Input_Downgrade
		case "$User_Input_Downgrade" in
			J|j) echo "Das Downgrade wird durchgeführt..."
			process_ge_proton_in_steam
				;;
			N|n|"") echo "Das Downgrade wird nicht durchgeführt. GE-Proton verbleibt auf Version $installed_ge_proton_version"
				;;
			*) echo "Falsche Eingabe! Als Eingabe werden nur 'J/j' und 'N/n' unterstützt."
			ask_downgrade_ge_proton
				;;
		esac
		}
		ask_downgrade_ge_proton
	elif [[ "$latest_ge_proton_version" -eq "$installed_ge_proton_version" ]]; then
		echo "GE-Proton ist aktuell: $installed_ge_proton_version"
	elif [[ "$latest_ge_proton_version" -lt "$installed_ge_proton_version" ]]; then
		echo "Neue GE-Proton-Version verfügbar:"
		echo "$installed_ge_proton_version --> $latest_ge_proton_version"
		process_ge_proton_in_steam
	fi
else
	echo "Folgende GE-Proton-Version wird hinzugefügt:"
	echo "$latest_ge_proton_version"
	process_ge_proton_in_steam
fi

echo ""

####################################
# GE-Proton Update (Lutris) prüfen #
####################################

process_ge_proton_in_lutris() {
	download_and_extract "$ge_proton_asset_url" "$LUTRIS_PROTON_DIR"
	echo "Erledigt."
	echo "Lösche altes GE-Proton-Verzeichnis..."
	rm -rf "$LUTRIS_PROTON_DIR"/ge-proton
	echo "Erledigt."
	echo "Benenne das GE-Proton-Verzeichnis um in 'ge-proton' zur Erkennung von 'GE-Proton (Latest)' für UMU..."
	mv "$LUTRIS_PROTON_DIR"/GE-Proton"$latest_ge_proton_version" "$LUTRIS_PROTON_DIR"/ge-proton
	echo "Erledigt."
}

echo "========== Lutris: GE-Proton =========="
echo "Prüfe auf eine neue Version von GE-Proton..."

latest_ge_proton_version=$(curl -s https://api.github.com/repos/GloriousEggroll/proton-ge-custom/releases/latest | jq -r .tag_name | cut -c 10-14)
ge_proton_asset_url=$(curl -s https://api.github.com/repos/GloriousEggroll/proton-ge-custom/releases/latest | jq -r '.assets[] | select(.name | endswith(".tar.gz")) | .browser_download_url')

if [[ -d "$LUTRIS_PROTON_DIR/ge-proton" ]] > /dev/null; then
	installed_ge_proton_version=$(cut -c 21-25 "$LUTRIS_PROTON_DIR"/ge-proton/version 2> /dev/null)
	if [[ "$latest_ge_proton_version" -gt "$installed_ge_proton_version" ]]; then
		echo "Warnung: Die vorhandene Version von GE-Proton ist neuer als die aktuellste Version im Github-Repository!"
		echo "$installed_ge_proton_version"" --> ""$latest_ge_proton_version"" (Downgrade!)"
		echo ""
		ask_downgrade_ge_proton() {
		read -r -p "Möchtest du ein Downgrade zulassen? (j/N): " User_Input_Downgrade
		case "$User_Input_Downgrade" in
			J|j) echo "Das Downgrade wird durchgeführt..."
			process_ge_proton_in_lutris
				;;
			N|n|"") echo "Das Downgrade wird nicht durchgeführt. GE-Proton verbleibt auf Version $installed_ge_proton_version"
				;;
			*) echo "Falsche Eingabe! Als Eingabe werden nur 'J/j' und 'N/n' unterstützt."
			ask_downgrade_ge_proton
				;;
		esac
		}
		ask_downgrade_ge_proton
	elif [[ "$latest_ge_proton_version" -eq "$installed_ge_proton_version" ]]; then
		echo "GE-Proton ist aktuell: $installed_ge_proton_version"
	elif [[ "$latest_ge_proton_version" -lt "$installed_ge_proton_version" ]]; then
		echo "Neue GE-Proton-Version verfügbar:"
		echo "$installed_ge_proton_version --> $latest_ge_proton_version"
		process_ge_proton_in_lutris
	fi
else
	echo "Folgende GE-Proton-Version wird hinzugefügt:"
	echo "$latest_ge_proton_version"
	process_ge_proton_in_lutris
fi

echo ""

#####################################################
# Wine-Staging-TkG (Repo: Kron4ek) Update prüfen    #
#####################################################

process_wine_staging_tkg_in_lutris() {
	download_and_extract "$wine_staging_tkg_asset_url" "$LUTRIS_WINE_DIR"
	mv "$LUTRIS_WINE_DIR"/wine-"$latest_wine_staging_tkg_version"-staging-tkg-amd64 "$LUTRIS_WINE_DIR/Wine $latest_wine_staging_tkg_version (Staging TkG Esync Fsync)"
	echo "Erledigt."
	echo "Lösche altes Wine (Staging TkG Esync Fsync)-Verzeichnis..."
	rm -rf "$LUTRIS_WINE_DIR/Wine $installed_wine_staging_tkg_version (Staging TkG Esync Fsync)"
	echo "Erledigt."
}

echo "========== Lutris: Wine =========="
echo "Prüfe auf eine neue Version von Wine (Staging TkG Esync Fsync)..."

latest_wine_staging_tkg_version=$(curl -s "https://api.github.com/repos/Kron4ek/Wine-Builds/releases?per_page=5" | jq -r '.[] | select(any(.assets[]?.name; test("tkg.amd64\\.tar\\.xz$"))) | .tag_name' | head -n 1) # Hardened against Proton releases, only recognizes Wine releases; extract version from latest wine release.
found_dir=$(find "$LUTRIS_WINE_DIR" -maxdepth 1 -type d -name 'Wine *.* (Staging TkG Esync Fsync)') # Find the existing Wine directory with the version number in it's name. Is needed because globbing is not allowed in IF statement.
wine_staging_tkg_asset_url=$(curl -s "https://api.github.com/repos/Kron4ek/Wine-Builds/releases?per_page=5" | jq -r '.[] | .assets[]? | select(.name | test("tkg.amd64\\.tar\\.xz$")) | .browser_download_url' | head -n 1) # Hardened against Proton releases, only recognizes Wine releases; contains download url for latest wine release.

if [[ -n "$found_dir" ]]; then
	installed_wine_staging_tkg_version=$(cut -c 18-22 "$LUTRIS_WINE_DIR/Wine "*.*"(Staging TkG Esync Fsync)/share/wine/wine.inf" 2> /dev/null | sed '2!d')
	version_compare "$installed_wine_staging_tkg_version" "$latest_wine_staging_tkg_version"
	if [[ "$result_compare" -eq 1 ]]; then
		echo "Warnung: Die vorhandene Version von Wine (Staging TkG Esync Fsync) ist neuer als die aktuellste Version im Github-Repository!"
		echo "$installed_wine_staging_tkg_version"" --> ""$latest_wine_staging_tkg_version"" (Downgrade!)"
		echo ""
		ask_downgrade_wine_staging_tkg() {
		read -r -p "Möchtest du ein Downgrade zulassen? (j/N): " User_Input_Downgrade
		case "$User_Input_Downgrade" in
			J|j) echo "Das Downgrade wird durchgeführt..."
			process_wine_staging_tkg_in_lutris
				;;
			N|n|"") echo "Das Downgrade wird nicht durchgeführt. Wine (Staging TkG Esync Fsync) verbleibt auf Version $installed_wine_staging_tkg_version"
				;;
			*) echo "Falsche Eingabe! Als Eingabe werden nur 'J/j' und 'N/n' unterstützt."
			ask_downgrade_wine_staging_tkg
				;;
		esac
		}
		ask_downgrade_wine_staging_tkg
	elif [[ "$result_compare" -eq 0 ]]; then
		echo "Wine (Staging TkG Esync Fsync) ist aktuell: $installed_wine_staging_tkg_version"
	elif [[ "$result_compare" -eq 2 ]]; then
		echo "Neue Wine (Staging TkG Esync Fsync)-Version verfügbar:"
		echo "$installed_wine_staging_tkg_version --> $latest_wine_staging_tkg_version"
		process_wine_staging_tkg_in_lutris
	fi
else
	echo "Folgende Wine (Staging TkG Esync Fsync)-Version wird hinzugefügt:"
	echo "$latest_wine_staging_tkg_version"
	process_wine_staging_tkg_in_lutris
fi

echo ""

#############################################################
# Wine-Staging-TkG-NTsync (Repo: Kron4ek) Update prüfen     #
#############################################################

process_wine_staging_tkg_ntsync_in_lutris() {
	download_and_extract "$wine_staging_tkg_ntsync_asset_url" "$LUTRIS_WINE_DIR"
	mv "$LUTRIS_WINE_DIR"/wine-"$latest_wine_staging_tkg_ntsync_version"-staging-tkg-ntsync-amd64-wow64 "$LUTRIS_WINE_DIR/Wine $latest_wine_staging_tkg_ntsync_version (Staging TkG NTsync)"
	echo "Erledigt."
	echo "Lösche altes Wine (Staging TkG NTsync)-Verzeichnis..."
	rm -rf "$LUTRIS_WINE_DIR/Wine $installed_wine_staging_tkg_ntsync_version (Staging TkG NTsync)"
	echo "Erledigt."
}

echo "========== Lutris: Wine =========="
echo "Prüfe auf eine neue Version von Wine (Staging TkG NTsync)..."

latest_wine_staging_tkg_ntsync_version=$(curl -s "https://api.github.com/repos/Kron4ek/Wine-Builds/releases?per_page=5" | jq -r '.[] | select(any(.assets[]?.name; test("ntsync.amd64.wow64\\.tar\\.xz$"))) | .tag_name' | head -n 1) # Hardened against Proton releases, only recognizes Wine releases; extract version from latest wine release.
found_dir=$(find "$LUTRIS_WINE_DIR" -maxdepth 1 -type d -name 'Wine *.* (Staging TkG NTsync)') # Find the existing Wine directory with the version number in it's name. Is needed because globbing is not allowed in IF statement.
wine_staging_tkg_ntsync_asset_url=$(curl -s "https://api.github.com/repos/Kron4ek/Wine-Builds/releases?per_page=5" | jq -r '.[] | .assets[]? | select(.name | test("ntsync.amd64.wow64\\.tar\\.xz$")) | .browser_download_url' | head -n 1) # Hardened against Proton releases, only recognizes Wine releases; contains download url for latest wine release.

if [[ -n "$found_dir" ]]; then
	installed_wine_staging_tkg_ntsync_version=$(cut -c 18-22 "$LUTRIS_WINE_DIR/Wine "*.*"(Staging TkG NTsync)/share/wine/wine.inf" 2> /dev/null | sed '2!d')
	version_compare "$installed_wine_staging_tkg_ntsync_version" "$latest_wine_staging_tkg_ntsync_version"
	if [[ "$result_compare" -eq 1 ]]; then
		echo "Warnung: Die vorhandene Version von Wine (Staging TkG NTsync) ist neuer als die aktuellste Version im Github-Repository!"
		echo "$installed_wine_staging_tkg_ntsync_version"" --> ""$latest_wine_staging_tkg_ntsync_version"" (Downgrade!)"
		echo ""
		ask_downgrade_wine_staging_tkg_ntsync() {
		read -r -p "Möchtest du ein Downgrade zulassen? (j/N): " User_Input_Downgrade
		case "$User_Input_Downgrade" in
			J|j) echo "Das Downgrade wird durchgeführt..."
			process_wine_staging_tkg_ntsync_in_lutris
				;;
			N|n|"") echo "Das Downgrade wird nicht durchgeführt. Wine (Staging TkG NTsync) verbleibt auf Version $installed_wine_staging_tkg_ntsync_version"
				;;
			*) echo "Falsche Eingabe! Als Eingabe werden nur 'J/j' und 'N/n' unterstützt."
			ask_downgrade_wine_staging_tkg_ntsync
				;;
		esac
		}
		ask_downgrade_wine_staging_tkg_ntsync
	elif [[ "$result_compare" -eq 0 ]]; then
		echo "Wine (Staging TkG NTsync) ist aktuell: $installed_wine_staging_tkg_ntsync_version"
	elif [[ "$result_compare" -eq 2 ]]; then
		echo "Neue Wine (Staging TkG NTsync)-Version verfügbar:"
		echo "$installed_wine_staging_tkg_ntsync_version --> $latest_wine_staging_tkg_ntsync_version"
		process_wine_staging_tkg_ntsync_in_lutris
	fi
else
	echo "Folgende Wine (Staging TkG NTsync)-Version wird hinzugefügt:"
	echo "$latest_wine_staging_tkg_ntsync_version"
	process_wine_staging_tkg_ntsync_in_lutris
fi

echo ""

#############################################################
# DXVK (Repo: doitsujin) Update prüfen                      #
#############################################################

echo "========== Lutris: DXVK =========="
echo "Prüfe auf eine neue Version von DXVK..."

latest_dxvk_version=$(curl -s https://api.github.com/repos/doitsujin/dxvk/releases/latest | jq -r .tag_name | cut -c 2-7)
installed_highest_dxvk_version=$(find "$LUTRIS_DXVK_DIR" -mindepth 1 -type d -name "v*" | sed 's|.*/v||' | sort -V | tail -n 1) # Find the highest DXVK release in LUTRIS_DXVK_DIR, version number is part of the directory name.
dxvk_asset_url=$(curl -s https://api.github.com/repos/doitsujin/dxvk/releases/latest | jq -r '.assets[] | select(.name | endswith(".tar.gz")) | .browser_download_url' | head -n 1)

version_compare "$installed_highest_dxvk_version" "$latest_dxvk_version"
if [[ "$result_compare" -eq 0 ]]; then
	echo "DXVK ist aktuell: $installed_highest_dxvk_version"
elif [[ "$result_compare" -eq 2 ]]; then
	echo "Neue DXVK-Version verfügbar:"
	echo "$installed_highest_dxvk_version --> $latest_dxvk_version"
	download_and_extract "$dxvk_asset_url" "$LUTRIS_DXVK_DIR"
	mv "$LUTRIS_DXVK_DIR"/vkd3d-proton-"$latest_dxvk_version" "$LUTRIS_DXVK_DIR/v$latest_dxvk_version"
	echo "Erledigt."
fi

echo ""

#############################################################
# VKD3D-Proton (Repo: HansKristian-Work) Update prüfen      #
#############################################################

echo "========== Lutris: VKD3D-Proton =========="
echo "Prüfe auf eine neue Version von VKD3D-Proton..."

latest_vkd3d_proton_version=$(curl -s https://api.github.com/repos/HansKristian-Work/vkd3d-proton/releases/latest | jq -r .tag_name | cut -c 2-7)
installed_highest_vkd3d_proton_version=$(find "$LUTRIS_VKD3D_PROTON_DIR" -mindepth 1 -type d -name "v*" | sed 's|.*/v||' | sort -V | tail -n 1) # Find the highest VKD3D-Proton release in LUTRIS_VKD3D_PROTON_DIR, version number is part of the directory name.
vkd3d_proton_asset_url=$(curl -s https://api.github.com/repos/HansKristian-Work/vkd3d-proton/releases/latest | jq -r '.assets[] | select(.name | endswith(".tar.zst")) | .browser_download_url')

version_compare "$installed_highest_vkd3d_proton_version" "$latest_vkd3d_proton_version"
if [[ "$result_compare" -eq 0 ]]; then
	echo "VKD3D-Proton ist aktuell: $installed_highest_vkd3d_proton_version"
elif [[ "$result_compare" -eq 2 ]]; then
	echo "Neue VKD3D-Proton-Version verfügbar:"
	echo "$installed_highest_vkd3d_proton_version --> $latest_vkd3d_proton_version"
	download_and_extract "$vkd3d_proton_asset_url" "$LUTRIS_VKD3D_PROTON_DIR"
	mv "$LUTRIS_VKD3D_PROTON_DIR"/vkd3d-proton-"$latest_vkd3d_proton_version" "$LUTRIS_VKD3D_PROTON_DIR/v$latest_vkd3d_proton_version"
	echo "Erledigt."
fi

echo ""

#############################################################
# DXVK-NVAPI (Repo: jp7677) Update prüfen                   #
#############################################################

echo "========== Lutris: DXVK-NVAPI =========="
echo "Prüfe auf eine neue Version von DXVK-NVAPI..."

latest_dxvk_nvapi_version=$(curl -s https://api.github.com/repos/jp7677/dxvk-nvapi/releases/latest | jq -r .tag_name | cut -c 2-6)
installed_highest_dxvk_nvapi_version=$(find "$LUTRIS_DXVK_NVAPI_DIR" -mindepth 1 -type d -name "v*" | sed 's|.*/v||' | sort -V | tail -n 1) # Find the highest DXVK-NVAPI release in LUTRIS_DXVK_NVAPI_DIR, version number is part of the directory name.
dxvk_nvapi_asset_url=$(curl -s https://api.github.com/repos/jp7677/dxvk-nvapi/releases/latest | jq -r '.assets[] | select(.name | endswith(".tar.gz")) | .browser_download_url')

version_compare "$installed_highest_dxvk_nvapi_version" "$latest_dxvk_nvapi_version"
if [[ "$result_compare" -eq 0 ]]; then
	echo "DXVK-NVAPI ist aktuell: $installed_highest_dxvk_nvapi_version"
elif [[ "$result_compare" -eq 2 ]]; then
	echo "Neue DXVK-NVAPI-Version verfügbar:"
	echo "$installed_highest_dxvk_nvapi_version --> $latest_dxvk_nvapi_version"
	download_and_extract "$dxvk_nvapi_asset_url" "$LUTRIS_DXVK_NVAPI_DIR"
	mv "$LUTRIS_DXVK_NVAPI_DIR"/dxvk-nvapi-"$latest_dxvk_nvapi_version" "$LUTRIS_DXVK_NVAPI_DIR/v$latest_dxvk_nvapi_version"
	echo "Erledigt."
fi

echo ""

echo "Fertig."

read -r

exit
