#!/bin/bash

# Audacity AppImage Porteus module build script (x86_64 only)
# Version 2026-09-05

export LC_ALL=C
export XZ_OPT="-T0"

BOLD=$'\033[1m'; CYAN=$'\033[96m'; GREEN=$'\033[92m'; RED=$'\033[31m'; YELLOW=$'\033[93m'; RESET=$'\033[0m'

[ "$(whoami)" != "root" ] && { printf "\n${RED}You need to be root to run this script.${RESET}\n"; exit 1; }

PRGNAM=${PRGNAM:-audacity}
BUILD=${BUILD:-1}
ARCH=$(uname -m)
CWD=$(pwd)
TMPDIR=/tmp/portch
PKG=$TMPDIR/package-$PRGNAM
PKGINFO=$PKG/var/lib/pkgtools/packages
OUTPUT=${OUTPUT:-/tmp}

[ "$ARCH" != "x86_64" ] && { printf "${RED}Error: Only x86_64 architecture is supported.${RESET}\n"; exit 1; }

cleanup() { rm -rf "$TMPDIR" "$PKG" 2>/dev/null; }
trap cleanup EXIT INT TERM HUP

printf "\nFetching latest release info...\n"
RELEASE_JSON=$(wget -q -O- "https://api.github.com/repos/audacity/audacity/releases/latest")
VERSION=$(printf '%s' "$RELEASE_JSON" | grep -m1 '"tag_name"' | sed -E 's/.*"Audacity-([0-9][0-9.]*).*/\1/')
[ -z "$VERSION" ] && { printf "${RED}Failed to determine version.${RESET}\n"; exit 1; }

DOWNLOAD_URL="https://github.com/audacity/audacity/releases/download/Audacity-${VERSION}/audacity-linux-${VERSION}-x86_64.AppImage"

INSTALLED_VERSION=""
[ -f "/opt/$PRGNAM/version.txt" ] && INSTALLED_VERSION=$(<"/opt/$PRGNAM/version.txt")

if [ "$INSTALLED_VERSION" = "$VERSION" ]; then
    printf "You have the latest ${GREEN}$INSTALLED_VERSION${RESET} version of $PRGNAM.\n"
    exit 0
else
    printf "Current: ${RED}${INSTALLED_VERSION:-None}${RESET} | Available: ${GREEN}$VERSION${RESET}\n"
    read -p "Build ${PRGNAM} ${GREEN}$VERSION${RESET} xzm module? [y/N]: " -n 1 -r -s && echo
    [[ ! $REPLY =~ ^[Yy]$ ]] && exit 0
fi

rm -rf "$PKG" "$TMPDIR"
mkdir -p "$PKG/opt/$PRGNAM" "$PKG/usr/bin" "$PKG/usr/share/applications" "$PKG/usr/share/pixmaps"
cd "$TMPDIR" || exit 1

APPIMAGE_NAME=$(basename "$DOWNLOAD_URL")
printf "\nDownloading ${CYAN}${BOLD}$APPIMAGE_NAME${RESET}\n"
wget -q --show-progress -O "$TMPDIR/$APPIMAGE_NAME" "$DOWNLOAD_URL"

[ -s "$TMPDIR/$APPIMAGE_NAME" ] || { printf "${RED}Download failed or file is empty.${RESET}\n"; exit 1; }

FTYPE=$(file -b "$TMPDIR/$APPIMAGE_NAME")
printf "File type: %s\n" "$FTYPE"
case "$FTYPE" in
    *x86-64*|*x86_64*) ;;
    *) printf "${RED}Error: AppImage is not x86_64. Aborting.${RESET}\n"; exit 1 ;;
esac

printf "\nExtracting AppImage...\n"
chmod +x "$TMPDIR/$APPIMAGE_NAME"

"$TMPDIR/$APPIMAGE_NAME" --appimage-extract >"$TMPDIR/extract.log" 2>&1

if [ ! -d squashfs-root ]; then
    printf "${CYAN}Runtime extract failed, trying unsquashfs...${RESET}\n"
    tail -n 3 "$TMPDIR/extract.log"
    OFFSET=$(grep -aobm1 "hsqs" "$TMPDIR/$APPIMAGE_NAME" 2>/dev/null | head -n 1 | cut -d: -f1)
    if [ -n "$OFFSET" ]; then
        tail -c +$((OFFSET+1)) "$TMPDIR/$APPIMAGE_NAME" > "$TMPDIR/payload.sqfs" 2>/dev/null
        unsquashfs -f -d squashfs-root "$TMPDIR/payload.sqfs" >>"$TMPDIR/extract.log" 2>&1
        rm -f "$TMPDIR/payload.sqfs"
    fi
fi

if [ ! -d squashfs-root ]; then
    printf "${RED}Extraction failed.${RESET}\n"
    tail -n 10 "$TMPDIR/extract.log"
    exit 1
fi

printf "${GREEN}Extraction successful.${RESET}\n"

mv squashfs-root/* "$PKG/opt/$PRGNAM/" 2>/dev/null
mv squashfs-root/.DirIcon "$PKG/opt/$PRGNAM/" 2>/dev/null
rmdir squashfs-root 2>/dev/null
rm -f "$TMPDIR/$APPIMAGE_NAME"

APP="$PKG/opt/$PRGNAM"

printf "\n${CYAN}Cleaning up unnecessary files...${RESET}\n"

rm -rf "$APP/share/themes" "$APP/lib/girepository-1.0" "$APP/share/metainfo" \
       "$APP/share/glib-2.0" "$APP/lib/audacity/engines-1.1" \
       "$APP/usr/share/X11" "$APP/share/X11"
rm -f "$APP/bin/check_dependencies" "$APP/bin/crashreporter" "$APP/bin/ldd_recursive" "$APP/bin/ldd-recursive" \
      "$APP/install_manifest.txt" \
      "$APP/audacity-url-handler.desktop" "$APP/share/applications/audacity-url-handler.desktop" \
      "$APP/audacity.desktop" "$APP/share/applications/audacity.desktop" \
      "$APP/share/audacity/nyquist/nyinit-dbg.lsp" "$APP/share/audacity/nyquist/test.lsp" \
      "$APP/share/audacity/nyquist-runtime/nyinit-dbg.lsp" "$APP/share/audacity/nyquist-runtime/test.lsp" \
      "$APP"/lib/libpcre2-8.so* "$APP"/lib/libpcre2-16.so* "$APP"/lib/libpcre2-32.so* \
      "$APP/lib/audacity/modules/mod-cloud-audiocom.so" "$APP/lib/audacity/modules/mod-musehub-ui.so"

# Extra cleanup: remove duplicate desktop files, mime data, nested wayland duplicates
rm -f "$APP/org.audacityteam.Audacity4portable.desktop" \
      "$APP/share/applications/org.audacityteam.Audacity4portable.desktop"
rm -rf "$APP/share/mime"
rm -rf "$APP/share/icons/hicolor"/*/mimetypes "$APP/share/icons/hicolor/scalable/mimetypes"
rm -rf "$APP/plugins/wayland-decoration-client/wayland-decoration-client" \
       "$APP/plugins/wayland-shell-integration/wayland-shell-integration"

find "$APP" -type d \( -name licenses -o -name doc -o -name docs -o -name man -o -name info -o -name authors \) -exec rm -rf {} + 2>/dev/null
find "$APP" -type f \( -iname "README*" -o -iname "LICENSE*" -o -iname "COPYING*" -o -iname "CHANGELOG*" -o -iname "AUTHORS*" -o -iname "*.md" \) -delete 2>/dev/null

if grep -q 'apprun-hooks' "$APP/AppRun" 2>/dev/null; then
    mkdir -p "$APP/apprun-hooks"
    grep -oE 'apprun-hooks/[A-Za-z0-9._-]+\.sh' "$APP/AppRun" 2>/dev/null | sort -u | while read -r h; do
        [ -e "$APP/$h" ] || printf '#!/bin/bash\n:\n' > "$APP/$h" 2>/dev/null
    done
fi

printf "  -> Stripping binaries...\n"
find "$APP" -type f -name "*.so*" -exec strip --strip-unneeded {} + 2>/dev/null
find "$APP/bin" "$APP/usr/bin" -type f -executable -exec strip --strip-unneeded {} + 2>/dev/null

# libsystemd stub
NEED_SYSTEMD=0
for f in $(find "$APP/bin" "$APP/lib" -type f 2>/dev/null); do
    file "$f" 2>/dev/null | grep -q "ELF" || continue
    if readelf -d "$f" 2>/dev/null | grep -q 'libsystemd\.so\.0'; then
        NEED_SYSTEMD=1
        printf "    (detected in %s)\n" "${f#$APP}"
        break
    fi
done

if [ $NEED_SYSTEMD -eq 1 ]; then
    printf "  -> Building libsystemd stub...\n"
    > "$TMPDIR/sd.list"
    for f in $(find "$APP/bin" "$APP/lib" -type f 2>/dev/null); do
        file "$f" 2>/dev/null | grep -q "ELF" || continue
        readelf -W --dyn-syms "$f" 2>/dev/null \
          | grep -E ' UND ' \
          | grep -oE 'sd_[A-Za-z0-9_]+(@[A-Za-z0-9_.]+)?'
    done >> "$TMPDIR/sd.list"
    sort -u "$TMPDIR/sd.list" -o "$TMPDIR/sd.list"
    [ -s "$TMPDIR/sd.list" ] || echo "sd_booted" > "$TMPDIR/sd.list"

    awk -F@ '{print $1}' "$TMPDIR/sd.list" | sort -u \
      | awk '{printf "int %s(){return -38;}\n", $1}' > "$TMPDIR/sdstub.c"

    awk '
    {
        if (index($0, "@") == 0) {
            base = base " " $0;
        } else {
            split($0, a, "@");
            sym = a[1];
            ver = a[2];
            v[ver] = v[ver] " " sym;
        }
    }
    END {
        if (base != "") {
            printf "LIBSYSTEMD_0 {\n    global:\n";
            n = split(base, syms, " ");
            for (i=1; i<=n; i++) if (syms[i] != "") printf "        %s;\n", syms[i];
            printf "    local:\n        *;\n};\n";
        }
        for (ver in v) {
            printf "%s {\n    global:\n", ver;
            n = split(v[ver], syms, " ");
            for (i=1; i<=n; i++) if (syms[i] != "") printf "        %s;\n", syms[i];
            printf "    local:\n        *;\n};\n";
        }
    }' "$TMPDIR/sd.list" > "$TMPDIR/sd.ver"

    gcc -shared -fPIC -Wl,--version-script="$TMPDIR/sd.ver" \
        -o "$APP/lib/libsystemd.so.0" "$TMPDIR/sdstub.c" 2>&1 | tail -n 5

    if [ -f "$APP/lib/libsystemd.so.0" ]; then
        printf "    ${GREEN}stub built: libsystemd.so.0${RESET}\n"
    else
        printf "    ${RED}stub build failed${RESET}\n"
    fi
fi

# locales
CORE_LOCALE_DIR=$(find "$APP" -maxdepth 6 -type d -path "*/share/locale" 2>/dev/null | head -n 1)
QM_MODE=0
if [ -z "$CORE_LOCALE_DIR" ]; then
    CORE_LOCALE_DIR=$(find "$APP" -maxdepth 6 -type d -name "locale" 2>/dev/null | head -n 1)
    [ -n "$CORE_LOCALE_DIR" ] && [ -n "$(ls "$CORE_LOCALE_DIR" 2>/dev/null | grep -m1 '\.qm$')" ] && QM_MODE=1
fi
printf "  -> Locale dir: %s\n" "${CORE_LOCALE_DIR:-not found}"
LANG_CHOICE="en"

if [ -n "$CORE_LOCALE_DIR" ]; then
    if [ $QM_MODE -eq 1 ]; then
        mapfile -t LANGUAGES < <(ls "$CORE_LOCALE_DIR" 2>/dev/null \
            | grep -E '^audacity_[a-z]{2,3}([_@][A-Za-z0-9]+)*\.qm$' \
            | sed -E 's/^audacity_//; s/\.qm$//' \
            | sort -u)
    else
        mapfile -t LANGUAGES < <(ls "$CORE_LOCALE_DIR" 2>/dev/null \
            | grep -E '^[a-z]{2,3}([_@][A-Za-z0-9]+)*$' \
            | sort -u)
    fi

    if [ ${#LANGUAGES[@]} -gt 0 ]; then
        printf "\n${CYAN}Audacity locale setup${RESET}\n"
        printf "Available locales (%s):\n" "${#LANGUAGES[@]}"

        COLS=5
        ROWS=$(( (${#LANGUAGES[@]} + COLS - 1) / COLS ))
        for ((i=0; i<ROWS; i++)); do
            for ((j=0; j<COLS; j++)); do
                idx=$((i + j * ROWS))
                if [ $idx -lt ${#LANGUAGES[@]} ]; then
                    num=$((idx + 1))
                    printf "  %2d) %-15s" "$num" "${LANGUAGES[$idx]}"
                fi
            done
            echo
        done

        while true; do
            echo
            read -p "Locale number to keep (en always kept) [1-${#LANGUAGES[@]}, Enter=en only]: " choice
            if [ -z "$choice" ]; then choice=0; break; fi
            [[ "$choice" =~ ^[0-9]+$ ]] && [ "$choice" -ge 1 ] && [ "$choice" -le "${#LANGUAGES[@]}" ] && break
            printf "${RED}Invalid input, try again.${RESET}\n"
        done

        [ "$choice" -gt 0 ] && LANG_CHOICE="${LANGUAGES[$((choice-1))]}"
    fi

    printf "  -> Removing locales except en and %s...\n" "$LANG_CHOICE"
    if [ $QM_MODE -eq 1 ]; then
        for f in "$CORE_LOCALE_DIR"/*.qm; do
            [ -e "$f" ] || continue
            bn=$(basename "$f" .qm)
            lang="${bn#*_}"
            case "$lang" in
                en|en_*|"$LANG_CHOICE"|"$LANG_CHOICE"_*) ;;
                *) rm -f "$f" ;;
            esac
        done
    else
        find "$CORE_LOCALE_DIR" -mindepth 1 -maxdepth 1 -type d ! -name "en*" ! -name "$LANG_CHOICE*" -exec rm -rf {} + 2>/dev/null
    fi
    printf "  -> Locales left: %s\n" "$(ls "$CORE_LOCALE_DIR" 2>/dev/null | grep -cE "audacity_(${LANG_CHOICE}|en)")"
fi

APPDATA_DIR=$(find "$APP/share" -maxdepth 1 -type d -name 'audacity4portable*' | head -n 1)
if [ -n "$APPDATA_DIR" ]; then
    mkdir -p "$APPDATA_DIR/plugins"
    # Create valid empty plugins.json in system location to avoid scan errors
    printf '{}' > "$APPDATA_DIR/plugins/plugins.json"
fi

find "$APP" -type f -name "lib*.so.*" | while read -r f; do
    d=$(dirname "$f"); b=$(basename "$f")
    link="${b%%.so.*}.so"
    [ -e "$d/$link" ] || ln -s "$b" "$d/$link" 2>/dev/null
done

PA_SRC=""
[ -f "$APP/lib/libportaudio.so" ] && PA_SRC="/opt/audacity/lib/libportaudio.so"
[ -z "$PA_SRC" ] && [ -f "$APP/fallback/libportaudio.so/libportaudio.so" ] && PA_SRC="/opt/audacity/fallback/libportaudio.so/libportaudio.so"
if [ -n "$PA_SRC" ]; then
    mkdir -p "$PKG/usr/lib64"
    ln -sf "$PA_SRC" "$PKG/usr/lib64/libportaudio.so.2"
    ln -sf libportaudio.so.2 "$PKG/usr/lib64/libportaudio.so"
fi

printf "\n${GREEN}Cleanup complete.${RESET}\n"

printf '%s' "$VERSION" > "$APP/version.txt"
chmod +x "$APP/AppRun" 2>/dev/null

cp "$APP/audacity4portable.png" "$PKG/usr/share/pixmaps/audacity.png" 2>/dev/null || \
cp "$APP/share/icons/hicolor/48x48/apps/audacity4portable.png" "$PKG/usr/share/pixmaps/audacity.png" 2>/dev/null || \
cp "$APP/audacity.png" "$PKG/usr/share/pixmaps/audacity.png" 2>/dev/null || \
cp "$APP/.DirIcon" "$PKG/usr/share/pixmaps/audacity.png" 2>/dev/null || \
wget -q -O "$PKG/usr/share/pixmaps/audacity.png" "https://slackbuilds.org/slackbuilds/15.0/audio/audacity/audacity.png"
chmod 644 "$PKG/usr/share/pixmaps/audacity.png"
rm -f "$APP/.DirIcon" "$APP/audacity.png" "$APP/audacity4portable.png"

find "$APP" -depth -type d -empty -delete 2>/dev/null

# Launcher (simplified, creates valid plugins.json)
cat > "$PKG/usr/bin/audacity" << 'EOF'
#!/bin/bash
export APPDIR=/opt/audacity
export LD_LIBRARY_PATH="$APPDIR/lib:$APPDIR/usr/lib:$APPDIR/usr/lib/x86_64-linux-gnu${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}"
[ -d "$APPDIR/lib/ffmpeg" ] && export LD_LIBRARY_PATH="$APPDIR/lib/ffmpeg:$LD_LIBRARY_PATH"

mkdir -p "$HOME/.local/share/Audacity/Audacity4/plugins"
# Create valid empty plugins.json to avoid read errors
[ -f "$HOME/.local/share/Audacity/Audacity4/plugins/plugins.json" ] || printf '{}' > "$HOME/.local/share/Audacity/Audacity4/plugins/plugins.json"
[ -f "$HOME/.local/share/Audacity/Audacity4/audiocom_cred.dat" ] || printf '{}' > "$HOME/.local/share/Audacity/Audacity4/audiocom_cred.dat"

cd "$APPDIR" || exit 1
[ "$AUDACITY_DEBUG" = "1" ] && exec ./AppRun "$@"
exec ./AppRun "$@"
EOF
chmod 755 "$PKG/usr/bin/audacity"

# Desktop file
cat > "$PKG/usr/share/applications/org.audacityteam.Audacity4portable.desktop" << EOM
[Desktop Entry]
Name=Audacity
GenericName=Audio Editor
GenericName[ru]=Аудиоредактор
Comment=Record and edit audio files
Comment[ru]=Запись и редактирование звука
Icon=/usr/share/pixmaps/audacity.png
Exec=audacity %F
Terminal=false
Type=Application
Categories=AudioVideo;Audio;AudioVideoEditing;
MimeType=application/x-audacity-project;audio/x-wav;audio/mpeg;audio/ogg;audio/flac;
StartupWMClass=audacity4portable
StartupNotify=true
EOM
chmod 644 "$PKG/usr/share/applications/org.audacityteam.Audacity4portable.desktop"

mkdir -p "$PKGINFO"
cat > "$PKGINFO/$PRGNAM-$VERSION-$ARCH" << EOM
PACKAGE NAME: $PRGNAM-$VERSION-$ARCH
PACKAGE DESCRIPTION:
audacity: Audacity is a free, easy-to-use, multi-track audio editor and recorder.
audacity: https://www.audacityteam.org/
FILE LIST:
EOM
cd "$PKG" || exit 1
find . -path ./var -prune -o -print | grep -v "^\./var" >> "$PKGINFO/$PRGNAM-$VERSION-$ARCH"
cd "$CWD" || exit 1

printf "\n${CYAN}Building XZM module...${RESET}\n"
dir2xzm "$PKG" "$OUTPUT/$PRGNAM-$VERSION-$ARCH-$BUILD.xzm"

if [ -f "$OUTPUT/$PRGNAM-$VERSION-$ARCH-$BUILD.xzm" ]; then
    MODULE_SIZE=$(du -h "$OUTPUT/$PRGNAM-$VERSION-$ARCH-$BUILD.xzm" | cut -f1)
    printf "\n${BOLD}[OK] Module successfully created!${RESET}\n"
    printf "${BOLD}Location: ${GREEN}$OUTPUT/$PRGNAM-$VERSION-${ARCH}-${BUILD}.xzm${RESET}\n"
    printf "${BOLD}Size: ${CYAN}$MODULE_SIZE${RESET}\n"
    printf "${BOLD}Action: Copy it to your /porteus/modules folder to survive a reboot.${RESET}\n\n"
else
    printf "\n${RED}${BOLD}[FAIL] Failed to build the module.${RESET}\n\n"
    exit 1
fi
