#!/bin/bash
#
# RetroArch 1.22.2 aus Lakka 6.1 für LibreELEC 12.2.1
# Zielgerät: Raspberry Pi 5 / aarch64
#
# Basierend auf dem ursprünglichen Skript von Andres Basile.
# Anpassungen:
# - SDL2-Bibliothek aus Lakka übernehmen
# - SDL2 isoliert unter /storage/retroarch/lib installieren
# - LD_LIBRARY_PATH im systemd-Dienst setzen
# - BusyBox-Kompatibilität berücksichtigen
# - Fehlerbehandlung und automatische Bereinigung
#
# Ausführung:
# bash retroarch_install.sh
#

set -Eeuo pipefail

######## SETTINGS ########

VERSION=6.1

# Raspberry Pi 5
DEVICE=RPi5
ARCH=aarch64

# Installationsverzeichnis
DIR_INSTALL="${HOME}/retroarch"

# Lakka Download
TRIPLET="Lakka-${DEVICE}.${ARCH}-${VERSION}"
TARFILE="${TRIPLET}.tar"
TARURL="https://github.com/libretro/Lakka-LibreELEC/releases/download/v${VERSION}/${TARFILE}"

# Verzeichnisse
DIR_TMP="${DIR_INSTALL}/tmp"
DIR_ROOTFS="${DIR_TMP}/rootfs"

# Systemintegration
DIR_SERVICE="${HOME}/.config/system.d"
DIR_FAVORITES="${HOME}/.kodi/userdata/favourites.xml"
DIR_CONFIG="${HOME}/.config/retroarch"

# Temporäre Variablen
LOOP_DEVICE=""
MOUNTED=0
DIR_START="${PWD}"

######## CLEANUP ########

cleanup() {
    RC=$?

    echo
    echo "Cleaning up..."

    if [ "$MOUNTED" -eq 1 ]; then
        umount "$DIR_ROOTFS" || true
    fi

    if [ -n "$LOOP_DEVICE" ]; then
        losetup -d "$LOOP_DEVICE" || true
    fi

    if [ -d "$DIR_TMP" ]; then
        rm -rf "$DIR_TMP"
    fi

    cd "$DIR_START" || true

    if [ "$RC" -eq 0 ]; then
        echo "Cleanup successful."
    else
        echo "Installation failed with exit code ${RC}."
        echo "The installation directory was retained for inspection."
    fi

    exit "$RC"
}

trap cleanup EXIT

######## CHECKS ########

echo "--- RetroArch Installation ---"
echo "Device: ${DEVICE}"
echo "Architecture: ${ARCH}"
echo "Lakka version: ${VERSION}"
echo "Install directory: ${DIR_INSTALL}"
echo "Download: ${TARURL}"
echo

if [ "$(id -u)" -ne 0 ]; then
    echo "ERROR: Please run this script as root."
    exit 1
fi

if [ ! -f /etc/release ]; then
    echo "ERROR: LibreELEC release information not found."
    exit 1
fi

RELEASE="$(cat /etc/release)"

echo "Detected LibreELEC: ${RELEASE}"

if [ "$RELEASE" != "RPi5.aarch64-12.2.1" ]; then
    echo "WARNING: This script was tested with RPi5.aarch64-12.2.1."
fi

if [ -e "$DIR_INSTALL" ]; then
    echo "ERROR: ${DIR_INSTALL} already exists."
    echo "Please back up or rename the existing installation first."
    exit 1
fi

if [ -e "$DIR_CONFIG" ]; then
    echo "ERROR: ${DIR_CONFIG} already exists."
    echo "Please back up or rename the existing configuration first."
    exit 1
fi

if ! command -v wget >/dev/null 2>&1; then
    echo "ERROR: wget not found."
    exit 1
fi

if ! command -v xml >/dev/null 2>&1; then
    echo "ERROR: xml (xmlstarlet) not found."
    exit 1
fi

if ! command -v losetup >/dev/null 2>&1; then
    echo "ERROR: losetup not found."
    exit 1
fi

if ! command -v systemctl >/dev/null 2>&1; then
    echo "ERROR: systemctl not found."
    exit 1
fi

echo "Checking available disk space..."

FREESPACE="$(df -m "$HOME" | awk 'END {print $4}')"

if [ "$FREESPACE" -lt 10000 ]; then
    echo "ERROR: Only ${FREESPACE} MB available."
    echo "At least 10000 MB required."
    exit 1
fi

echo "Available space: ${FREESPACE} MB"

######## CREATE DIRECTORIES ########

echo
echo "Creating installation directories..."

mkdir -p "$DIR_INSTALL"
mkdir -p "$DIR_INSTALL/filters"
mkdir -p "$DIR_INSTALL/lib"
mkdir -p "$DIR_TMP"
mkdir -p "$DIR_ROOTFS"

######## DOWNLOAD ########

echo
echo "Downloading Lakka ${VERSION}..."

cd "$DIR_TMP"

wget -O "$TARFILE" "$TARURL"

if [ ! -s "$TARFILE" ]; then
    echo "ERROR: Download failed or archive is empty."
    exit 1
fi

######## EXTRACT SYSTEM IMAGE ########

echo
echo "Extracting Lakka SYSTEM image..."

tar -xf "$TARFILE" \
    --strip-components=1 \
    "${TRIPLET}/target/SYSTEM.md5" \
    "${TRIPLET}/target/SYSTEM"

if [ ! -f target/SYSTEM ]; then
    echo "ERROR: SYSTEM image not found."
    exit 1
fi

if [ ! -f target/SYSTEM.md5 ]; then
    echo "ERROR: SYSTEM.md5 not found."
    exit 1
fi

######## VERIFY MD5 ########

echo
echo "Checking MD5..."

cd "$DIR_TMP"
md5sum -c target/SYSTEM.md5

######## MOUNT SYSTEM IMAGE ########

echo
echo "Attaching SYSTEM image to loop device..."

LOOP_DEVICE="$(losetup --show -f target/SYSTEM)"

if [ -z "$LOOP_DEVICE" ]; then
    echo "ERROR: Could not attach loop device."
    exit 1
fi

echo "Loop device: ${LOOP_DEVICE}"

echo "Mounting Lakka root filesystem..."

mount -o ro "$LOOP_DEVICE" "$DIR_ROOTFS"
MOUNTED=1

######## COPY RETROARCH ########

echo
echo "Copying RetroArch binary..."

if [ ! -f "$DIR_ROOTFS/usr/bin/retroarch" ]; then
    echo "ERROR: RetroArch binary not found."
    exit 1
fi

cp -a "$DIR_ROOTFS/usr/bin/retroarch" "$DIR_INSTALL/"

######## COPY ASSETS ########

echo
echo "Copying RetroArch assets..."

du -sh "$DIR_ROOTFS/usr/share/retroarch"

cp -a "$DIR_ROOTFS/usr/share/retroarch/assets" "$DIR_INSTALL/"
cp -a "$DIR_ROOTFS/usr/share/retroarch/overlays" "$DIR_INSTALL/"
cp -a "$DIR_ROOTFS/usr/share/retroarch/shaders" "$DIR_INSTALL/"
cp -a "$DIR_ROOTFS/usr/share/retroarch/system" "$DIR_INSTALL/"

######## COPY CORES ########

echo
echo "Copying Libretro cores..."

du -sh "$DIR_ROOTFS/usr/lib/libretro"

cp -a "$DIR_ROOTFS/usr/lib/libretro" "$DIR_INSTALL/cores"

######## COPY DATABASE ########

echo
echo "Copying Libretro database..."

du -sh "$DIR_ROOTFS/usr/share/libretro-database"

cp -a "$DIR_ROOTFS/usr/share/libretro-database" "$DIR_INSTALL/database"

######## COPY FILTERS ########

echo
echo "Copying audio and video filters..."

cp -a "$DIR_ROOTFS/usr/share/video_filters" "$DIR_INSTALL/filters/video"
cp -a "$DIR_ROOTFS/usr/share/audio_filters" "$DIR_INSTALL/filters/audio"

######## COPY SDL2 ########

echo
echo "Copying SDL2 libraries..."

if ! ls "$DIR_ROOTFS"/usr/lib/libSDL2* >/dev/null 2>&1; then
    echo "ERROR: SDL2 libraries not found in Lakka image."
    exit 1
fi

cp -a "$DIR_ROOTFS"/usr/lib/libSDL2* "$DIR_INSTALL/lib/"

echo "Installed SDL2 files:"
ls -l "$DIR_INSTALL/lib/"

######## CHECK DEPENDENCIES ########

echo
echo "Checking RetroArch dependencies..."

LDD_OUTPUT="$(LD_LIBRARY_PATH="$DIR_INSTALL/lib" ldd "$DIR_INSTALL/retroarch" 2>&1)"

echo "$LDD_OUTPUT"

if echo "$LDD_OUTPUT" | grep -q "not found"; then
    echo
    echo "ERROR: Missing shared libraries detected."
    echo "Installation will not be integrated into Kodi."
    exit 1
fi

######## SYNC ########

echo
echo "Syncing filesystem..."

sync

######## CREATE SYSTEMD SERVICE ########

echo
echo "Creating systemd service..."

mkdir -p "$DIR_SERVICE"

cat <<EOF > "${DIR_SERVICE}/retroarch.service"
[Unit]
Description=RetroArch
After=network-online.target graphical.target
Requires=graphical.target
Wants=network-online.target

[Service]
EnvironmentFile=/usr/lib/kodi/kodi.conf
Environment=LD_LIBRARY_PATH=${DIR_INSTALL}/lib
ExecStartPre=systemctl stop kodi
ExecStart=${DIR_INSTALL}/retroarch
ExecStopPost=systemctl start kodi
TimeoutStopSec=10
Restart=no
LimitNOFILE=16384

[Install]
WantedBy=kodi.target
EOF

######## RELOAD SYSTEMD ########

echo
echo "Reloading systemd..."

systemctl daemon-reload

systemctl disable retroarch || true

######## CREATE WRAPPER ########

echo
echo "Creating Kodi wrapper..."

cat <<EOF > "${DIR_INSTALL}/retroarch.py"
from xbmc import executebuiltin
from subprocess import run

executebuiltin(
    'Notification(RetroArch, Loading..., 5000, ${DIR_INSTALL}/assets/xmb/monochrome/png/retroarch.png)'
)

run(["/usr/bin/systemctl", "start", "retroarch"])
EOF

######## CREATE FAVORITE ########

echo
echo "Creating Kodi favorite..."

mkdir -p "$(dirname "$DIR_FAVORITES")"

if [ ! -e "$DIR_FAVORITES" ]; then
    cat <<EOF > "$DIR_FAVORITES"
<?xml version="1.0"?>
<favourites>
</favourites>
EOF
fi

xml ed \
    -L \
    -s "/favourites" -t elem -n "favourite" \
    -v "RunScript(${DIR_INSTALL}/retroarch.py)" \
    -i "/favourites/favourite[last()]" -t attr -n "name" -v "RetroArch" \
    -i "/favourites/favourite[last()]" -t attr -n "thumb" \
    -v "${DIR_INSTALL}/assets/xmb/monochrome/png/retroarch.png" \
    "$DIR_FAVORITES"

######## CONFIGURATION LINK ########

echo
echo "Creating RetroArch configuration link..."

ln -s "$DIR_INSTALL" "$DIR_CONFIG"

######## FINISH ########

echo
echo "Installation completed successfully!"
echo
echo "RetroArch version:"
LD_LIBRARY_PATH="$DIR_INSTALL/lib" "$DIR_INSTALL/retroarch" --version

echo
echo "Installation directory: ${DIR_INSTALL}"
echo "SDL2 directory: ${DIR_INSTALL}/lib"
echo "Service: ${DIR_SERVICE}/retroarch.service"
echo "Kodi favorite: RetroArch"
echo
echo "RetroArch can now be started from Kodi Favorites."
echo

sync
