#!/usr/bin/env bash
# Cross-compile nibtools' nibconv (NIB/NBZ -> G64/D64 disk image converter)
# as a static library for Android.
# Called automatically by Gradle; can also be run manually:
#   export NDK=/path/to/android-ndk && bash build_nibtools.sh
#
# Output: nibtools-libs/arm64-v8a/libnibtools.a
#         nibtools-libs/x86_64/libnibtools.a
#
# Only nibconv's pure file-format conversion code is built — gcr.c, prot.c,
# fileio.c, crc.c, md5.c, lz.c and nibconv.c itself. The hardware-access
# parts of nibtools (nibread/nibwrite, talking to a real 1541 over OpenCBM)
# are not built and not needed; see nibtools_android/opencbm.h for why that
# dependency can be stubbed out instead of vendored.

set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
TARBALL="${SCRIPT_DIR}/../../../../res/nibtools-91344e0ee3.tar.gz"
SRC="${SCRIPT_DIR}/nibtools-src"
ANDROID_SHIM="${SCRIPT_DIR}/nibtools_android"

: "${NDK:?NDK env var must point to the Android NDK root}"

echo "=== build_nibtools.sh ==="
echo "  SCRIPT_DIR : ${SCRIPT_DIR}"
echo "  TARBALL    : ${TARBALL}"
echo "  SRC        : ${SRC}"
echo "  NDK        : ${NDK}"

TOOLCHAIN="${NDK}/toolchains/llvm/prebuilt/linux-x86_64"
if [ ! -d "${TOOLCHAIN}" ]; then
    echo "ERROR: NDK toolchain not found at ${TOOLCHAIN}" >&2
    exit 1
fi

if [ ! -f "${TARBALL}" ]; then
    echo "ERROR: nibtools tarball not found at ${TARBALL}" >&2
    exit 1
fi

if [ ! -d "${SRC}" ]; then
    echo "Unpacking nibtools..."
    tar -xzf "${TARBALL}" -C "${SCRIPT_DIR}"
    # Hardcoded, not a glob: on a non-ephemeral runner workspace, a
    # nibtools-*/ glob can also match SRC itself once it exists, or other
    # stray nibtools-prefixed leftovers, and mv then fails with "target is
    # not a directory" (multiple sources, no existing target dir).
    mv "${SCRIPT_DIR}/nibtools-91344e0ee3" "${SRC}"
    echo "Unpacked to ${SRC}"
fi

# Pure conversion sources — no hardware/OpenCBM access (see header comment above).
SOURCES="gcr.c prot.c fileio.c crc.c md5.c lz.c nibconv.c"

build_abi() {
    local ABI="$1"
    local HOST="$2"
    local API=24
    local CC="${TOOLCHAIN}/bin/${HOST}${API}-clang"
    local AR="${TOOLCHAIN}/bin/llvm-ar"
    local OUT="${SCRIPT_DIR}/nibtools-libs/${ABI}"
    local BUILD_DIR="/tmp/nibtools-android-${ABI}"

    echo ""
    echo "--- ABI: ${ABI} ---"

    if [ -f "${OUT}/libnibtools.a" ]; then
        echo "  libnibtools.a already exists — skipping"
        return 0
    fi
    if [ ! -f "${CC}" ]; then
        echo "ERROR: Clang not found at ${CC}" >&2
        exit 1
    fi

    mkdir -p "${BUILD_DIR}" "${OUT}"

    for src in ${SOURCES}; do
        local obj="${BUILD_DIR}/$(basename "${src}" .c).o"
        local extra_defs=""
        # nibconv.c's main() is renamed at compile time so it can be linked
        # into a shared library (which already has its own JNI entry points)
        # without clashing with libc's startup expectations for `main`.
        if [ "${src}" = "nibconv.c" ]; then
            extra_defs="-Dmain=nibtools_nibconv_main"
        fi
        "${CC}" -std=c99 -O2 -fPIC ${extra_defs} \
            -I "${ANDROID_SHIM}" -I "${SRC}" \
            -c "${SRC}/${src}" -o "${obj}"
    done

    "${AR}" -crs "${OUT}/libnibtools.a" "${BUILD_DIR}"/*.o
    echo "  Built ${OUT}/libnibtools.a"
}

build_abi "arm64-v8a" "aarch64-linux-android"
build_abi "x86_64"    "x86_64-linux-android"

echo ""
echo "=== nibtools build complete ==="
