#!/usr/bin/env bash
#
# Build FFmpeg as UNIVERSAL (arm64 + x86_64) shared libraries for Syncer.
#
# Produces fat dylibs + headers under Scripts/ffmpeg/dist/ :
#   dist/lib/libavcodec.dylib   (arm64 + x86_64)
#   dist/lib/libavformat.dylib
#   dist/lib/libavutil.dylib
#   dist/lib/libswscale.dylib
#   dist/lib/libswresample.dylib
#   dist/include/...
#
# LICENSING: this is an LGPL-clean, DECODE-focused build. No --enable-gpl,
# no x264/x265 (those are GPL / separately licensed for ENCODE). Decoders for
# MXF long-GOP (XAVC/XDCAM = H.264/MPEG-2), AVC-Intra, ProRes, DNxHD, etc. are
# all LGPL and included. We rely on VideoToolbox / AVAssetWriter for ENCODE, so
# FFmpeg is used purely to DECODE what AVFoundation can't open.
#
# Prereqs (install once):  brew install nasm pkg-config
# Run:                     ./build-ffmpeg-universal.sh
#
set -euo pipefail

FFMPEG_VERSION="${FFMPEG_VERSION:-7.1}"
HERE="$(cd "$(dirname "$0")" && pwd)"
BUILD="$HERE/build"
DIST="$HERE/dist"
SRC="$BUILD/ffmpeg-$FFMPEG_VERSION"
MIN_MACOS="12.0"   # match/inform the app's deployment floor
# Neutral install prefix. configure bakes its full command line into every
# dylib (avutil_configuration()), so a prefix under the build machine's home
# folder would ship the builder's username and folder layout in the binary.
# Install goes through DESTDIR instead; the libs' install names are @rpath, so
# the prefix never matters at runtime.
PREFIX="/opt/ffmpeg"

command -v nasm >/dev/null      || { echo "ERROR: nasm not found — run: brew install nasm"; exit 1; }
command -v pkg-config >/dev/null|| { echo "ERROR: pkg-config not found — run: brew install pkg-config"; exit 1; }

mkdir -p "$BUILD"
cd "$BUILD"

# ── Fetch source ──────────────────────────────────────────────────────────
if [ ! -d "$SRC" ]; then
  echo "▶ Fetching FFmpeg ${FFMPEG_VERSION}…"
  curl -L "https://ffmpeg.org/releases/ffmpeg-$FFMPEG_VERSION.tar.xz" -o ffmpeg.tar.xz
  tar xf ffmpeg.tar.xz
  rm -f ffmpeg.tar.xz
fi

# Shared configure flags: LGPL, shared libs, decode-only surface, no CLI/docs.
common_flags=(
  --enable-shared --disable-static
  --enable-pic
  --disable-programs --disable-doc --disable-htmlpages --disable-manpages
  --disable-gpl --disable-nonfree
  # We DECODE with FFmpeg and ENCODE with AVFoundation/VideoToolbox, so drop
  # FFmpeg's own encoders/muxers/filters/devices to shrink the libs and stay
  # licence-clean. Demuxers + decoders + swscale/swresample are what we need.
  --disable-encoders --disable-muxers --disable-filters
  --disable-devices --disable-avdevice
  --disable-network
  --enable-demuxers --enable-decoders --enable-parsers --enable-protocols
  # configure AUTODETECTS optional libraries on the build machine, and a
  # Homebrew libX11 got linked into every lib this way (for VAAPI/VDPAU
  # hardware decoding, which macOS doesn't have). The app then died at launch
  # on every Mac: the path doesn't exist there, and dyld refuses a Homebrew
  # dylib inside a Developer ID app even where it does. Name them off
  # explicitly — pkg-config below is fenced off too.
  --disable-xlib --disable-libxcb --disable-vaapi --disable-vdpau
  --disable-sdl2
  --install-name-dir=@rpath
)

# Nothing from Homebrew may be found through pkg-config: every optional
# dependency this build uses is part of macOS itself.
export PKG_CONFIG_LIBDIR="$BUILD/no-pkgconfig"
export PKG_CONFIG_PATH=""
mkdir -p "$PKG_CONFIG_LIBDIR"

build_arch () {
  local arch="$1"
  local out="$BUILD/out-$arch"
  echo "▶ Configuring FFmpeg for ${arch}…"
  rm -rf "$out"; mkdir -p "$out"
  ( cd "$SRC" && make distclean >/dev/null 2>&1 || true )

  local cflags="-arch $arch -mmacosx-version-min=$MIN_MACOS"
  local ldflags="-arch $arch -mmacosx-version-min=$MIN_MACOS"
  local cross=""
  # Cross-compile flag when building the non-host arch.
  local host_arch; host_arch="$(uname -m)"
  if [ "$arch" != "$host_arch" ]; then
    cross="--enable-cross-compile --arch=$arch --target-os=darwin"
  fi

  ( cd "$SRC" && ./configure \
      --prefix="$PREFIX" \
      "${common_flags[@]}" \
      $cross \
      --extra-cflags="$cflags" \
      --extra-ldflags="$ldflags" \
    && make -j"$(sysctl -n hw.ncpu)" \
    && make install DESTDIR="$out" )
}

build_arch arm64
build_arch x86_64

# ── lipo the two arches into universal dylibs + copy headers ──────────────
echo "▶ Creating universal (fat) libraries…"
rm -rf "$DIST"; mkdir -p "$DIST/lib" "$DIST/include"
cp -R "$BUILD/out-arm64$PREFIX/include/." "$DIST/include/"

for lib in libavcodec libavformat libavutil libswscale libswresample; do
  a="$(ls "$BUILD/out-arm64$PREFIX/lib/$lib".*.dylib 2>/dev/null | head -1 || true)"
  x="$(ls "$BUILD/out-x86_64$PREFIX/lib/$lib".*.dylib 2>/dev/null | head -1 || true)"
  [ -n "$a" ] && [ -n "$x" ] || { echo "  ! missing $lib for one arch"; continue; }
  base="$(basename "$a")"          # e.g. libavcodec.61.19.100.dylib
  lipo -create "$a" "$x" -output "$DIST/lib/$base"
  # The install name uses the MAJOR-version SONAME (@rpath/libavcodec.61.dylib),
  # which is what dyld resolves at load time — create that symlink plus the
  # unversioned alias used for linking. Missing the major-version link is the
  # classic "Library not loaded: @rpath/libavcodec.61.dylib" launch crash.
  major="$(echo "$base" | sed -E "s/^$lib\.([0-9]+)\..*/\1/")"
  ( cd "$DIST/lib"
    ln -sf "$base" "$lib.$major.dylib"
    ln -sf "$base" "$lib.dylib" )
  echo "  ✓ $lib  →  $(lipo -archs "$DIST/lib/$base")  (soname $lib.$major.dylib)"
done

# ── Refuse libs that link anything outside macOS or each other ────────────
# A dependency on a file only the build machine has (/opt/homebrew, /usr/local)
# passes signing and notarisation and then fails to launch everywhere else.
bad=0
for f in "$DIST/lib"/*.dylib; do
  [ -L "$f" ] && continue
  ext="$(otool -L "$f" | awk '/^\t/{print $1}' \
         | grep -vE '^(/usr/lib/|/System/Library/|@rpath/)' || true)"
  if [ -n "$ext" ]; then
    echo "  ✗ $(basename "$f") links outside macOS:"; echo "$ext" | sed 's/^/      /'
    bad=1
  fi
done
[ "$bad" = 0 ] || { echo "ERROR: FFmpeg libs have external dependencies — not usable in the app."; exit 1; }
echo "  ✓ no external library dependencies"

echo
echo "✅ Done. Universal libs in: $DIST/lib"
echo "   Point Package.swift's FFmpeg C target at $DIST/include and $DIST/lib."
