#!/bin/bash

# This is multilib-lite build script of xzm module for Porteus
# Version 2026-08-16

# Copyright 2023-2030, Blaze, Dankov, Russia
# All rights reserved.
#
# Redistribution and use of this script, with or without modification, is
# permitted provided that the following conditions are met:
#
# 1. Redistributions of this script must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
#
#  THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED
#  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
#  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO
#  EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
#  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
#  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
#  OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
#  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
#  OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
#  ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

# Root check
if [ "$(whoami)" != "root" ]; then
    echo -e "\nOnly root can run this.\n"
    exit 1
fi

BOLD=${BOLD:-"\e[1m"}
CYAN=${CYAN:-"\e[96m"}
GREEN=${GREEN:-"\e[92m"}
RED=${RED:-"\e[31m"}
YELLOW=${YELLOW:-"\e[93m"}
RESET=${RESET:-"\e[0m"}

# Detect Slackware version (stable or current)
systemFullVersion=$(cat /etc/slackware-version 2>/dev/null)
systemVersion=${systemFullVersion//* }

if [[ "$systemFullVersion" == *"current"* ]] || [[ "$systemVersion" == *"+"* ]]; then
    export SLACKWAREVERSION=current
    export PORTEUSBUILD=current
else
    export SLACKWAREVERSION=$systemVersion
    export PORTEUSBUILD=stable
fi

export SLACKBUILDVERSION=$SLACKWAREVERSION
echo -e "\n${BOLD}Slackware base: ${CYAN}slackware-$SLACKWAREVERSION${RESET}"
echo -e "${BOLD}Porteus build:  ${CYAN}$PORTEUSBUILD${RESET}\n"

PRGNAM=${PRGNAM:-0050-multilib-lite}
BUILD=${BUILD:-1}
TAG=${TAG:-bl}
MIRROR=${MIRROR:-"http://mirror.yandex.ru/slackware"}
SLACKDIR="$MIRROR/slackware-$SLACKWAREVERSION"
BASE="$SLACKDIR/slackware"
DATE=$(date +%Y%m%d)

echo -e "${BOLD}Mirror: ${CYAN}$MIRROR${RESET}"
echo -e "${BOLD}Base:   ${CYAN}$BASE${RESET}\n"

CWD=$(pwd)
TMP=${TMP:-/tmp/SBo}
PKG=$TMP/package-$PRGNAM
OUTPUT=${OUTPUT:-/tmp}

rm -rf $PKG
mkdir -p $TMP $PKG $OUTPUT
cd $TMP
rm -rf $PRGNAM

# Associative array: series -> package list (sorted alphabetically)
declare -A PKG_LISTS=(
    [a]="aaa_glibc-solibs acl attr bzip2 dbus eudev openssl-solibs util-linux \
         xz"
    [d]="gcc gcc-g++ llvm"
    [l]="alsa-lib alsa-plugins brotli cairo elfutils expat freetype fribidi \
         gdk-pixbuf2 giflib glib2 gmp graphite2 gst-plugins-base gstreamer gtk+2 \
         harfbuzz icu4c lame libasyncns libcap libedit libffi libidn2 \
         libjpeg-turbo libnsl libogg libpcap libpng libpsl libsndfile libssh2 \
         libtasn1 libtheora libtiff libunistring libunwind libusb libvorbis \
         libxkbcommon libxml2 libxslt lz4 ncurses openal-soft opus orc pango pcre2 \
         pulseaudio readline sdl SDL2 SDL2_image SDL2_mixer v4l-utils zlib zstd"
    [n]="curl gnutls libgcrypt libgpg-error libtirpc nettle nghttp2 p11-kit"
    [ap]="cups flac lm_sensors mpg123"
    [x]="fontconfig freeglut glu intel-gmmlib intel-media-driver intel-vaapi-driver \
         libdisplay-info libdrm libglvnd libICE libpciaccess libSM libva libvdpau \
         libX11 libXau libxcb libXcomposite libXcursor libXdamage libXdmcp libXext \
         libXfixes libXft libXi libXinerama libXmu libXpm libXrandr libXrender \
         libXScrnSaver libxshmfence libXt libXtst libXv libXxf86vm mesa pixman \
         vulkan-sdk wayland xcb-util xcb-util-image xcb-util-keysyms \
         xcb-util-renderutil xcb-util-wm"
    [xap]="sane"
)

WGET_OPTS="--quiet --progress=bar:force:noscroll --max-redirect=20 --tries=2 --timeout=30"

# ==============================================================================
# Fetch fresh CHECKSUMS.md5 unconditionally to avoid 404s on updated packages
# ==============================================================================
CHECKSUMS_FILE="$TMP/CHECKSUMS.md5"
echo -e "${CYAN}Fetching fresh CHECKSUMS.md5...${RESET}"
rm -f "$CHECKSUMS_FILE"
if ! wget $WGET_OPTS "$BASE/CHECKSUMS.md5" -O "$CHECKSUMS_FILE" 2>/tmp/wget.err; then
    echo -e "${RED}Failed to download CHECKSUMS.md5${RESET}" >&2
    [ -s /tmp/wget.err ] && sed 's/^/  /' /tmp/wget.err >&2
    exit 1
fi
if [ ! -s "$CHECKSUMS_FILE" ]; then
    echo -e "${RED}CHECKSUMS.md5 is empty${RESET}" >&2
    exit 1
fi
echo -e "${GREEN}CHECKSUMS.md5 updated: $(du -h "$CHECKSUMS_FILE" | cut -f1)${RESET}\n"

# Function to get package path from CHECKSUMS.md5
get_pkg_file() {
    local series="$1" name="$2"
    local checksums="$CHECKSUMS_FILE"

    # Escape regex special characters in package name
    local escaped_name
    escaped_name=$(printf '%s' "$name" | sed 's/[][\.*^$()+?{|]/\\&/g')

    local match
    match=$(grep -E -i "\./${series}/${escaped_name}-[0-9]" "$checksums" \
              | grep -E -- "-(i[56]86|noarch)-" \
              | grep '\.txz$' \
              | tail -1 \
              | awk '{print $2}' \
              | sed 's|^\./||; s|.*/||')

    if [ -z "$match" ]; then
        local similar
        similar=$(grep -i "\./${series}/${escaped_name}" "$checksums" | grep '\.txz$' | head -2)
        if [ -n "$similar" ]; then
            echo -e "${YELLOW}  (similar found in CHECKSUMS: $(echo "$similar" | awk '{print $2}' | sed 's|^\./||; s|.*/||' | tr '\n' ' '))${RESET}" >&2
        fi
    fi

    echo "$match"
}

# Download packages
cd $PKG
downloaded=0

for series in "${!PKG_LISTS[@]}"; do
    for name in ${PKG_LISTS[$series]}; do
        file=$(get_pkg_file "$series" "$name")
        if [ -n "$file" ]; then
            echo -e "${CYAN}[$series]${RESET} $file"
            if wget $WGET_OPTS -O "$file" "$BASE/$series/$file" 2>/tmp/wget.err; then
                downloaded=$((downloaded + 1))
            else
                echo -e "${RED}[WARN]${RESET} download failed: $file"
                [ -s /tmp/wget.err ] && sed 's/^/  /' /tmp/wget.err
                rm -f "$file"
            fi
        else
            echo -e "${RED}[WARN]${RESET} not found: $name"
        fi
    done
done

echo -e "\n${BOLD}Downloaded: ${GREEN}$downloaded${RESET} packages\n"

if [ "$downloaded" -eq 0 ]; then
    echo -e "${RED}${BOLD}Error: no packages downloaded.${RESET}\n"
    exit 1
fi

if [ -z "$(ls -A "$PKG"/*.txz 2>/dev/null)" ]; then
    echo -e "${RED}${BOLD}Error: no .txz files found in $PKG${RESET}\n"
    exit 1
fi

# Determine architecture from downloaded packages
ARCH=""
for f in "$PKG"/*.txz; do
    if [ -f "$f" ]; then
        base=$(basename "$f")
        if [[ "$base" =~ -([^-]+)-[0-9]+\.txz$ ]]; then
            ARCH="${BASH_REMATCH[1]}"
            break
        fi
    fi
done
if [ -z "$ARCH" ]; then
    ARCH="i586"
fi
echo -e "${BOLD}Detected architecture: ${CYAN}$ARCH${RESET}\n"

# Install all packages into $PKG
ROOT="$PKG" installpkg "$PKG"/*.txz

# ============================================================
# CLEANUP (lite module)
# ============================================================
rm -f *.txz
rm -rf $PKG/{KEEP,run,tmp,install}
rm -rf $PKG/usr/{doc,man,info,src,libexec}
rm -rf $PKG/usr/lib/{.build-id,cmake,pkgconfig,gtk-doc,girepository-1.0}
rm -rf $PKG/usr/share/{doc,gtk-doc,help,i18n,locale,pkgconfig,gir-1.0}
rm -rf $PKG/usr/share/{applications,icons,themes,pixmaps,wallpapers,sounds}
rm -rf $PKG/{etc,run,dev,proc,sys}
rm -rf $PKG/var/{log,cache,tmp}

# Remove /usr/sbin entirely
rm -rf $PKG/usr/sbin

# Remove /usr/bin contents except vulkaninfo (needed for diagnostics)
if [ -d "$PKG/usr/bin" ]; then
    find "$PKG/usr/bin" -mindepth 1 -maxdepth 1 ! -name 'vulkaninfo' -exec rm -rf {} +
fi

# Remove headers and static libs (runtime only)
find $PKG -type f \( -name '*.a' -o -name '*.la' -o -name '*.o' -o -name '*.h' -o -name '*.pc' \) -delete
find $PKG -type f \( -iname 'README*' -o -iname 'LICENSE*' -o -iname 'COPYING*' \
                     -o -iname 'ChangeLog*' -o -iname 'AUTHORS' -o -iname 'NEWS' \
                     -o -iname 'TODO' -o -iname '*.md' \) -delete
find $PKG/usr/lib -type d -name 'python*' -prune -exec rm -rf {} + 2>/dev/null
find $PKG -type d -name '.build-id' -prune -exec rm -rf {} + 2>/dev/null

# ===== CLEANUP: vulkan-sdk =====
# Keep: libvulkan.so.1 (loader), vulkaninfo binary
# Remove: validation layers, profiles layer, dev files, extra tools
echo -e "${BOLD}Cleaning up vulkan-sdk (keeping only loader + vulkaninfo)...${RESET}"

# Remove Vulkan validation and profiling layers (dev-only)
find $PKG -type f -iname '*VkLayer*' -delete
find $PKG -type f -iname '*VkLayer*.json' -delete

# Remove Vulkan SDK documentation and samples
rm -rf $PKG/usr/share/vulkan-sdk 2>/dev/null
rm -rf $PKG/usr/share/doc/vulkan* 2>/dev/null

# Remove extra vulkan-sdk tools (keep only vulkaninfo for diagnostics)
for bin in apitrace vkconfig vkcube vkcubepp vkvia vktrace; do
    find $PKG -type f -name "$bin" -delete
done

# Remove Vulkan static libs if any
find $PKG -type f \( -name 'libvulkan.a' -o -name 'libvulkan*.la' \) -delete

# Remove Vulkan headers (already removed globally, but double-check)
rm -rf $PKG/usr/include/vulkan 2>/dev/null

# Ensure ICD directory from mesa is preserved
mkdir -p $PKG/usr/share/vulkan/icd.d
mkdir -p $PKG/usr/share/vulkan/explicit_layer.d
mkdir -p $PKG/usr/share/vulkan/implicit_layer.d

# Remove empty Vulkan dirs (except icd.d which may have mesa files)
find $PKG/usr/share/vulkan -mindepth 1 -maxdepth 1 -type d -empty -delete 2>/dev/null
# ===== END CLEANUP: vulkan-sdk =====

# Clean var/lib
find $PKG/var/lib -mindepth 1 -maxdepth 1 -type d ! -name 'pkgtools' -exec rm -rf {} + 2>/dev/null
find $PKG/var/lib/pkgtools -mindepth 1 -maxdepth 1 -type d ! -name 'packages' -exec rm -rf {} + 2>/dev/null

# Remove top-level directories that are not lib, usr, var
find $PKG -mindepth 1 -maxdepth 1 -type d ! -name 'lib' ! -name 'usr' ! -name 'var' -exec rm -rf {} + 2>/dev/null

# Remove empty directories
find $PKG -depth -type d -empty -delete

# ============================================================
# CREATE SYMBOLIC LINKS (compatibility)
# ============================================================
echo -e "${BOLD}Creating symbolic links for compatibility...${RESET}"

# libudev.so.0 -> libudev.so.1 (Steam runtime expects old version)
# Search in both /lib and /usr/lib, create symlink in same directory as source
libudev_found=""
libudev_dir=""
for dir in "$PKG/lib" "$PKG/usr/lib"; do
    if [ -e "$dir/libudev.so.1" ] || [ -L "$dir/libudev.so.1" ]; then
        libudev_found="libudev.so.1"
        libudev_dir="$dir"
        break
    fi
done

if [ -n "$libudev_found" ] && [ -n "$libudev_dir" ]; then
    ln -sf "$libudev_found" "$libudev_dir/libudev.so.0"
    echo -e "  ${GREEN}Created:${RESET} ${libudev_dir#$PKG}/libudev.so.0 -> $libudev_found"
else
    echo -e "  ${YELLOW}WARN:${RESET} libudev.so.1 not found in package"
fi

# ============================================================
# CHECKS
# ============================================================
echo -e "\n${BOLD}Checking critical 32-bit libraries:${RESET}"

check_lib() {
    local libname="$1"
    local found=0
    for dir in "$PKG/lib" "$PKG/usr/lib"; do
        if [ -e "$dir/$libname" ] || [ -L "$dir/$libname" ]; then
            echo -e "  ${GREEN}OK:${RESET} $libname (in ${dir#$PKG/})"
            found=1
            break
        fi
    done
    if [ $found -eq 0 ]; then
        echo -e "  ${RED}MISSING:${RESET} $libname"
        return 1
    fi
    return 0
}

missing=0
for lib in ld-linux.so.2 libc.so.6 libstdc++.so.6 libgcc_s.so.1; do
    check_lib "$lib" || missing=1
done

# Check libLLVM (needed for llvmpipe)
if ls "$PKG"/usr/lib/libLLVM*.so* >/dev/null 2>&1; then
    echo -e "  ${GREEN}OK:${RESET} libLLVM"
else
    echo -e "  ${RED}MISSING:${RESET} libLLVM"
    missing=1
fi

# Check libGL variants
if [ -e "$PKG/usr/lib/libGL.so.1" ] || [ -L "$PKG/usr/lib/libGL.so.1" ] || \
   [ -e "$PKG/usr/lib/libGLX_mesa.so.0" ] || [ -e "$PKG/usr/lib/libGLX.so.0" ]; then
    echo -e "  ${GREEN}OK:${RESET} libGL variant found"
else
    echo -e "  ${RED}MISSING:${RESET} libGL variant"
    missing=1
fi

# Check Vulkan loader
echo -e "\n${BOLD}Checking Vulkan support:${RESET}"
if [ -e "$PKG/usr/lib/libvulkan.so.1" ] || [ -L "$PKG/usr/lib/libvulkan.so.1" ]; then
    echo -e "  ${GREEN}OK:${RESET} libvulkan.so.1"
else
    echo -e "  ${YELLOW}WARN:${RESET} libvulkan.so.1 not found (Vulkan may not work)"
fi

# Check Wine-specific libraries
echo -e "\n${BOLD}Checking Wine-specific libraries:${RESET}"
for lib in libxslt.so.1 libpcap.so.1; do
    check_lib "$lib" || missing=1
done

# Check Steam-specific libraries (added packages)
echo -e "\n${BOLD}Checking Steam-specific libraries:${RESET}"
for lib in libpciaccess.so.0 libdisplay-info.so.4 libedit.so.0 libsensors.so.5; do
    check_lib "$lib" || missing=1
done

# Check symbolic links
echo -e "\n${BOLD}Checking symbolic links:${RESET}"
libudev_link_found=0
for dir in "$PKG/lib" "$PKG/usr/lib"; do
    if [ -L "$dir/libudev.so.0" ]; then
        target=$(readlink -f "$dir/libudev.so.0" 2>/dev/null || readlink "$dir/libudev.so.0")
        echo -e "  ${GREEN}OK:${RESET} ${dir#$PKG}/libudev.so.0 -> $(basename "$target")"
        libudev_link_found=1
        break
    fi
done
if [ $libudev_link_found -eq 0 ]; then
    echo -e "  ${YELLOW}WARN:${RESET} libudev.so.0 not found (Steam runtime compatibility)"
fi

if [ $missing -ne 0 ]; then
    echo -e "${RED}${BOLD}Error: critical libraries missing. Module not built.${RESET}\n"
    exit 1
fi

echo -e "${GREEN}All critical libraries are present.${RESET}\n"

# ============================================================
# BUILD MODULE
# ============================================================
XZM_NAME="$PRGNAM-$PORTEUSBUILD-$DATE.xzm"
XZM_FILE="$OUTPUT/$XZM_NAME"

if ! dir2xzm "$PKG" "$XZM_FILE"; then
    echo -e "${RED}${BOLD}Error: dir2xzm failed${RESET}\n"
    exit 1
fi

# Check result
if [ -f "$XZM_FILE" ]; then
    SIZE=$(du -h "$XZM_FILE" | cut -f1)
    echo -e "\n${BOLD}Module $PRGNAM created: ${GREEN}${BOLD}$XZM_FILE${RESET}"
    echo -e "${BOLD}Size: ${CYAN}$SIZE${RESET}"
    echo -e "${BOLD}Move it to your modules folder to survive a reboot.${RESET}\n"
else
    echo -e "\n${RED}${BOLD}Error. Module not built.${RESET}\n"
fi
