#!/usr/bin/env bash
#
# build-dependencies.sh
#
# Builds the NextNote FFmpeg dependencies inside an MSYS2 UCRT64 shell:
# nv-codec-headers (header + pkg-config install, no build) and libvpl
# (static dispatcher). AMD's AMF component is
# headers-only and dynamically loaded at runtime, so it needs no build step
# -- it is only referenced by include path.
#
# Run via scripts/build.ps1, which extracts the pinned sources and invokes
# this script inside MSYS2 with the paths below as positional arguments (all
# in MSYS POSIX form, e.g. /c/nnffb/...). Not intended to be run standalone;
# no argument defaults or re-derivation of the dependency lock happens here
# -- build.ps1 is the single place that reads config/dependencies.lock.json.
#
# Usage:
#   build-dependencies.sh <sources_dir> <deps_prefix> \
#       <nvheaders_root_name> <libvpl_root_name>
#
# Produces, under <deps_prefix>:
#   include/, lib/, lib/pkgconfig/    -- ffnvcodec.pc, vpl.pc
#   build-dependencies-manifest.txt   -- versions of every tool actually used

set -euo pipefail

if [ "$#" -ne 4 ]; then
    echo "usage: $0 <sources_dir> <deps_prefix> <nvheaders_root_name> <libvpl_root_name>" >&2
    exit 2
fi

SOURCES_DIR="$1"
DEPS_PREFIX="$2"
NVHEADERS_ROOT_NAME="$3"
LIBVPL_ROOT_NAME="$4"

NVHEADERS_DIR="$SOURCES_DIR/$NVHEADERS_ROOT_NAME"
LIBVPL_DIR="$SOURCES_DIR/$LIBVPL_ROOT_NAME"

for d in "$NVHEADERS_DIR" "$LIBVPL_DIR"; do
    [ -d "$d" ] || { echo "ERROR: expected source directory not found: $d" >&2; exit 1; }
done

mkdir -p "$DEPS_PREFIX"
NPROC="$(nproc 2>/dev/null || echo 4)"
MANIFEST="$DEPS_PREFIX/build-dependencies-manifest.txt"
: > "$MANIFEST"
log() { echo "$@" | tee -a "$MANIFEST"; }

log "=== Toolchain ==="
log "gcc:    $(gcc --version | head -n1)"
log "cmake:  $(cmake --version | head -n1)"
log "ninja:  $(ninja --version)"
log "make:   $(make --version | head -n1)"
log "nasm:   $(nasm -v)"
log "pkgconf: $(pkgconf --version 2>/dev/null || pkg-config --version)"
log ""

# ---------------------------------------------------------------------------
log "=== 1. nv-codec-headers (headers + ffnvcodec.pc, no build step) ==="
cd "$NVHEADERS_DIR"
make install PREFIX="$DEPS_PREFIX"
log "nv-codec-headers: installed to $DEPS_PREFIX/include/ffnvcodec"
log ""

# ---------------------------------------------------------------------------
log "=== 2. libvpl (static dispatcher lib + vpl.pc) ==="
LIBVPL_BUILD="$LIBVPL_DIR/build"
rm -rf "$LIBVPL_BUILD"
mkdir -p "$LIBVPL_BUILD"
cd "$LIBVPL_BUILD"
# -ffunction-sections/-fdata-sections (Milestone 4 minimisation): same
# lets the final link's -Wl,--gc-sections trim
# unused code out of this statically-linked archive too.
cmake -G Ninja \
    -DCMAKE_BUILD_TYPE=Release \
    -DCMAKE_INSTALL_PREFIX="$DEPS_PREFIX" \
    -DBUILD_SHARED_LIBS=OFF \
    -DBUILD_TESTS=OFF \
    -DBUILD_TOOLS=OFF \
    -DBUILD_EXAMPLES=OFF \
    -DCMAKE_C_FLAGS="-ffunction-sections -fdata-sections" \
    -DCMAKE_CXX_FLAGS="-ffunction-sections -fdata-sections" \
    "$LIBVPL_DIR" \
    | tee -a "$MANIFEST"
cmake --build . --config Release -j"$NPROC"
cmake --install . --config Release
log "libvpl: installed to $DEPS_PREFIX"
log ""

# ---------------------------------------------------------------------------
log "=== 2b. Patch vpl.pc: absolute paths + C++ runtime link ==="
# Two independent problems in libvpl's CMake-generated vpl.pc, both found by
# inspecting FFmpeg's ffbuild/config.log during Milestone 2 authoring:
#
# 1. includedir/libdir are defined relative to \${pcfiledir} (e.g.
#    includedir=\${pcfiledir}/../../include). This build of pkgconf (3.0.3+,
#    MSYS2 UCRT64) mis-joins that pattern on Windows, silently dropping the
#    path separator and producing a corrupted path such as
#    "C:/nnffb/depsinclude" instead of "C:/nnffb/deps/include" -- this broke
#    the mfxvideo.h/mfxdispatcher.h header check even though
#    pkg-config --exists/--modversion both succeeded standalone.
#    nv-codec-headers' ffnvcodec.pc, which uses an absolute prefix (via
#    cygpath), does not trigger this bug -- fixed by using the same
#    absolute-path style here instead of relative pcfiledir arithmetic.
#
# 2. libvpl's dispatcher (mfx_dispatcher(_vpl).cpp) is C++, using operator
#    new/delete, C++ exceptions, and RTTI -- but vpl.pc's Libs.private is
#    empty. FFmpeg's configure links its pkg-config test programs with the
#    plain C compiler (gcc), which -- unlike the g++ front-end -- does not
#    automatically add libstdc++. The result was "undefined reference to
#    operator new / __cxa_begin_catch / __gxx_personality_seh0 / vtable for
#    __cxxabiv1::__class_type_info" even after fix #1 resolved the header
#    check. Since --pkg-config-flags=--static makes configure combine Libs
#    and Libs.private, declaring -lstdc++ as a private (static-link-only)
#    dependency here is the correct fix -- it is not part of libvpl's public
#    API, only an implementation-language runtime requirement.
VPL_PC="$DEPS_PREFIX/lib/pkgconfig/vpl.pc"
sed -i \
    -e "s|^prefix=.*|prefix=$DEPS_PREFIX|" \
    -e "s|^libdir=.*|libdir=\${prefix}/lib|" \
    -e "s|^includedir=.*|includedir=\${prefix}/include|" \
    -e "s|^Libs\.private:.*|Libs.private: -lstdc++|" \
    "$VPL_PC"
if grep -q 'pcfiledir' "$VPL_PC"; then
    echo "ERROR: vpl.pc still contains pcfiledir-relative paths after patching:" >&2
    cat "$VPL_PC" >&2
    exit 1
fi
if ! grep -q '^Libs\.private:.*-lstdc++' "$VPL_PC"; then
    echo "ERROR: vpl.pc Libs.private does not contain -lstdc++ after patching:" >&2
    cat "$VPL_PC" >&2
    exit 1
fi
log "vpl.pc patched (absolute paths + -lstdc++):"
cat "$VPL_PC" | tee -a "$MANIFEST"
log ""

# ---------------------------------------------------------------------------
log "=== Result ==="
log "pkgconfig files:"
ls -1 "$DEPS_PREFIX/lib/pkgconfig/" | tee -a "$MANIFEST"

for pc in ffnvcodec vpl; do
    if [ ! -f "$DEPS_PREFIX/lib/pkgconfig/$pc.pc" ]; then
        echo "ERROR: expected $pc.pc not found in $DEPS_PREFIX/lib/pkgconfig -- FFmpeg's configure will not find this dependency." >&2
        exit 1
    fi
done
log "Both pkg-config files (ffnvcodec.pc, vpl.pc) are present."
log "Dependency build complete. Manifest: $MANIFEST"
