#!/bin/bash
# Cross-build the RV1106 third-party runtime with a consistent mbedTLS ABI.
set -euo pipefail
export LC_ALL=C

HERE="$(cd "$(dirname "$0")" && pwd)"
SRC="$HERE/src"
BUILD="$HERE/build"
INSTALL="${WEBRTCPUSH_DEPS:-$HERE/install}"
mkdir -p "$SRC" "$BUILD" "$INSTALL"

export RV1106_SDK="${RV1106_SDK:-$HOME/rv1106sdk/luckfox-pico}"
TC_DIR="$RV1106_SDK/tools/linux/toolchain/arm-rockchip830-linux-uclibcgnueabihf"
export PATH="$TC_DIR/bin:$PATH"
export WEBRTCPUSH_DEPS="$INSTALL"
TOOLCHAIN_FILE="$HERE/../cmake/toolchain-rv1106.cmake"
CROSS=arm-rockchip830-linux-uclibcgnueabihf
JOBS="${JOBS:-$(nproc)}"
RV1106_ARCH_FLAGS="-mfpu=neon-vfpv4 -mfloat-abi=hard"
export RV1106_ARCH_FLAGS

MBEDTLS_VER="${MBEDTLS_VER:-3.6.6}"
MBEDTLS_SHA256="${MBEDTLS_SHA256:-8fb65fae8dcae5840f793c0a334860a411f884cc537ea290ce1c52bb64ca007a}"
CURL_VER="${CURL_VER:-8.6.0}"
CURL_BUILD_REV="${CURL_BUILD_REV:-3}"
DTC_TAG="${DTC_TAG:-v0.21.2}"
MOSQUITTO_VER="${MOSQUITTO_VER:-2.0.22}"
MBEDTLS_MARKER="$INSTALL/.ok-mbedtls-$MBEDTLS_VER"
CURL_MARKER="$INSTALL/.ok-curl-$CURL_VER-mbedtls-$MBEDTLS_VER-r$CURL_BUILD_REV"
DTC_MARKER="$INSTALL/.ok-datachannel-$DTC_TAG-mbedtls-$MBEDTLS_VER"
MOSQUITTO_MARKER="$INSTALL/.ok-mosquitto-$MOSQUITTO_VER"

log() { printf '[%s] %s\n' "$(date +%H:%M:%S)" "$*"; }
die() { printf '[FAIL] %s\n' "$*" >&2; exit 1; }
need() { command -v "$1" >/dev/null 2>&1 || die "missing tool: $1"; }

need git
need curl
need cmake
need make
need pkg-config
need python3
need sha256sum

copy_nlohmann_headers() {
  local source_dir="$SRC/libdatachannel/deps/json"
  local header_dir=""
  if [ -d "$source_dir/single_include/nlohmann" ]; then
    header_dir="$source_dir/single_include/nlohmann"
  elif [ -d "$source_dir/include/nlohmann" ]; then
    header_dir="$source_dir/include/nlohmann"
  fi
  [ -n "$header_dir" ] || die "nlohmann/json headers not found in libdatachannel"
  mkdir -p "$INSTALL/include"
  cp -a "$header_dir" "$INSTALL/include/"
}

apply_datachannel_patch() {
  local patch_file="$HERE/../cmake/libdatachannel-v0.21.2-mbedtls-dtls-read-length.patch"
  [ -f "$patch_file" ] || die "missing libdatachannel DTLS patch: $patch_file"
  cd "$SRC/libdatachannel"
  if git apply --check "$patch_file" >/dev/null 2>&1; then
    git apply "$patch_file"
    log "applied libdatachannel mbedTLS DTLS read-length patch"
  elif git apply --reverse --check "$patch_file" >/dev/null 2>&1; then
    log "libdatachannel DTLS patch already applied"
  else
    die "libdatachannel DTLS patch does not apply cleanly"
  fi
}

build_mbedtls() {
  if [ -f "$MBEDTLS_MARKER" ]; then
    log "mbedTLS $MBEDTLS_VER already built"
    return
  fi

  local archive="$SRC/mbedtls-$MBEDTLS_VER.tar.bz2"
  local source_dir="$SRC/mbedtls-$MBEDTLS_VER"
  log "building mbedTLS $MBEDTLS_VER"
  if [ ! -d "$source_dir" ]; then
    if [ ! -f "$archive" ]; then
      curl -fsSL \
        "https://github.com/Mbed-TLS/mbedtls/releases/download/mbedtls-$MBEDTLS_VER/mbedtls-$MBEDTLS_VER.tar.bz2" \
        -o "$archive" || die "failed to download mbedTLS"
    fi
    printf '%s  %s\n' "$MBEDTLS_SHA256" "$archive" | sha256sum -c - \
      || die "mbedTLS archive checksum failed"
    tar xf "$archive" -C "$SRC" || die "failed to extract mbedTLS"
  else
    log "using vendored mbedTLS source: $source_dir"
  fi

  python3 "$source_dir/scripts/config.py" set MBEDTLS_SSL_DTLS_SRTP \
    || die "failed to enable MBEDTLS_SSL_DTLS_SRTP"
  rm -rf "$BUILD/mbedtls-$MBEDTLS_VER"
  cmake -S "$source_dir" -B "$BUILD/mbedtls-$MBEDTLS_VER" \
    -DCMAKE_TOOLCHAIN_FILE="$TOOLCHAIN_FILE" \
    -DCMAKE_INSTALL_PREFIX="$INSTALL" \
    -DCMAKE_BUILD_TYPE=Release \
    -DENABLE_TESTING=OFF \
    -DENABLE_PROGRAMS=OFF \
    -DMBEDTLS_FATAL_WARNINGS=OFF \
    -DUSE_SHARED_MBEDTLS_LIBRARY=ON \
    -DUSE_STATIC_MBEDTLS_LIBRARY=OFF \
    || die "mbedTLS configure failed"
  cmake --build "$BUILD/mbedtls-$MBEDTLS_VER" -j"$JOBS" \
    || die "mbedTLS build failed"
  rm -f "$INSTALL"/lib/libmbedcrypto.so* \
    "$INSTALL"/lib/libmbedtls.so* \
    "$INSTALL"/lib/libmbedx509.so*
  cmake --install "$BUILD/mbedtls-$MBEDTLS_VER" \
    || die "mbedTLS install failed"
  printf '%s\n' "$MBEDTLS_VER" > "$MBEDTLS_MARKER"
}

build_curl() {
  if [ -f "$CURL_MARKER" ]; then
    log "curl $CURL_VER with mbedTLS $MBEDTLS_VER already built"
    return
  fi
  [ -f "$MBEDTLS_MARKER" ] || build_mbedtls

  log "building curl $CURL_VER"
  cd "$SRC"
  if [ ! -d curl ]; then
    curl -fsSL "https://curl.se/download/curl-$CURL_VER.tar.gz" -o curl.tar.gz \
      || die "failed to download curl"
    tar xf curl.tar.gz || die "failed to extract curl"
    mv "curl-$CURL_VER" curl
  fi
  rm -rf "$BUILD/curl-$CURL_VER-mbedtls-$MBEDTLS_VER"
  mkdir -p "$BUILD/curl-$CURL_VER-mbedtls-$MBEDTLS_VER"
  cd "$BUILD/curl-$CURL_VER-mbedtls-$MBEDTLS_VER"
  "$SRC/curl/configure" \
    --host="$CROSS" \
    --prefix="$INSTALL" \
    --with-mbedtls="$INSTALL" \
    --without-openssl --without-gnutls --without-wolfssl \
    --without-libssh2 --without-libssh --without-librtmp \
    --without-brotli --without-zstd --without-nghttp2 \
    --without-libidn2 --without-libpsl \
    --disable-ldap --disable-ldaps --disable-rtsp --disable-dict \
    --disable-telnet --disable-tftp --disable-pop3 --disable-imap \
    --disable-smtp --disable-gopher --disable-mqtt --disable-manual \
    --disable-ftp --disable-file --enable-shared --disable-static \
    --disable-dependency-tracking \
    CC="$CROSS-gcc" \
    CFLAGS="$RV1106_ARCH_FLAGS" \
    CPPFLAGS="-I$INSTALL/include" \
    LDFLAGS="-L$INSTALL/lib" \
    LIBS="-lmbedtls -lmbedx509 -lmbedcrypto" \
    PKG_CONFIG_PATH="$INSTALL/lib/pkgconfig" \
    || die "curl configure failed"
  make -j"$JOBS" -C lib V=1 || die "curl build failed"
  make -C lib install || die "curl install failed"
  cp -a lib/.libs/libcurl.so* "$INSTALL/lib/" \
    || die "curl shared library install failed"
  mkdir -p "$INSTALL/include"
  cp -a "$SRC/curl/include/curl" "$INSTALL/include/"
  printf '%s\n' "$CURL_VER + mbedTLS $MBEDTLS_VER" > "$CURL_MARKER"
}

build_datachannel() {
  if [ -f "$DTC_MARKER" ]; then
    copy_nlohmann_headers
    log "libdatachannel $DTC_TAG with mbedTLS $MBEDTLS_VER already built"
    return
  fi
  [ -f "$MBEDTLS_MARKER" ] || build_mbedtls

  log "building libdatachannel $DTC_TAG"
  cd "$SRC"
  if [ ! -d libdatachannel ]; then
    git clone --depth 1 --recursive --branch "$DTC_TAG" \
      https://github.com/paullouisageneau/libdatachannel.git \
      || die "failed to clone libdatachannel"
  else
    cd libdatachannel
    if [ -d .git ]; then
      git submodule update --init --recursive \
        || die "failed to update libdatachannel submodules"
    elif [ ! -f deps/json/CMakeLists.txt ] || [ ! -f deps/libjuice/CMakeLists.txt ]; then
      die "vendored libdatachannel source is missing submodule contents"
    else
      log "using vendored libdatachannel source and submodules"
    fi
    cd ..
  fi
  apply_datachannel_patch
  rm -rf "$BUILD/datachannel-$DTC_TAG-mbedtls-$MBEDTLS_VER"
  cmake -S "$SRC/libdatachannel" \
    -B "$BUILD/datachannel-$DTC_TAG-mbedtls-$MBEDTLS_VER" \
    -DCMAKE_TOOLCHAIN_FILE="$TOOLCHAIN_FILE" \
    -DCMAKE_INSTALL_PREFIX="$INSTALL" \
    -DCMAKE_BUILD_TYPE=Release \
    -DCMAKE_PREFIX_PATH="$INSTALL" \
    -DUSE_MBEDTLS=ON \
    -DNO_USRSCTP=ON \
    -DNO_WEBSOCKET=OFF \
    -DNO_EXAMPLES=ON \
    -DNO_TESTS=ON \
    -DCMAKE_INSTALL_RPATH='\$ORIGIN' \
    || die "libdatachannel configure failed"
  cmake --build "$BUILD/datachannel-$DTC_TAG-mbedtls-$MBEDTLS_VER" -j"$JOBS" \
    || die "libdatachannel build failed"
  cmake --install "$BUILD/datachannel-$DTC_TAG-mbedtls-$MBEDTLS_VER" \
    || die "libdatachannel install failed"
  copy_nlohmann_headers
  printf '%s\n' "$DTC_TAG + mbedTLS $MBEDTLS_VER" > "$DTC_MARKER"
}

build_mosquitto() {
  if [ -f "$MOSQUITTO_MARKER" ]; then
    log "libmosquitto $MOSQUITTO_VER already built"
    return
  fi

  local source_dir="$SRC/mosquitto"
  log "building libmosquitto $MOSQUITTO_VER"
  if [ ! -d "$source_dir" ]; then
    git clone --depth 1 --branch "v$MOSQUITTO_VER" \
      https://github.com/eclipse-mosquitto/mosquitto.git "$source_dir" \
      || die "failed to clone Mosquitto"
  else
    log "using vendored Mosquitto source: $source_dir"
  fi

  rm -rf "$BUILD/mosquitto-$MOSQUITTO_VER"
  cmake -S "$source_dir" -B "$BUILD/mosquitto-$MOSQUITTO_VER" \
    -DCMAKE_TOOLCHAIN_FILE="$TOOLCHAIN_FILE" \
    -DCMAKE_INSTALL_PREFIX="$INSTALL" \
    -DCMAKE_BUILD_TYPE=Release \
    -DWITH_TLS=OFF \
    -DWITH_TLS_PSK=OFF \
    -DWITH_EC=OFF \
    -DWITH_CJSON=OFF \
    -DWITH_LIB_CPP=OFF \
    -DWITH_CLIENTS=OFF \
    -DWITH_BROKER=OFF \
    -DWITH_APPS=OFF \
    -DWITH_PLUGINS=OFF \
    -DDOCUMENTATION=OFF \
    -DWITH_STATIC_LIBRARIES=OFF \
    -DWITH_THREADING=ON \
    -DWITH_SOCKS=OFF \
    -DWITH_UNIX_SOCKETS=OFF \
    || die "Mosquitto configure failed"
  cmake --build "$BUILD/mosquitto-$MOSQUITTO_VER" -j"$JOBS" \
    || die "Mosquitto build failed"
  cmake --install "$BUILD/mosquitto-$MOSQUITTO_VER" \
    || die "Mosquitto install failed"
  printf '%s\n' "$MOSQUITTO_VER" > "$MOSQUITTO_MARKER"
}

summary() {
  log "installed libraries in $INSTALL/lib"
  ls -la "$INSTALL/lib" | grep -E '\.so' || true
}

TARGET="${1:-all}"
case "$TARGET" in
  mbedtls) build_mbedtls ;;
  curl) build_curl ;;
  datachannel) build_datachannel ;;
  mosquitto) build_mosquitto ;;
  all)
    build_mbedtls
    build_curl
    build_datachannel
    build_mosquitto
    ;;
  *) die "unknown target: $TARGET (expected mbedtls, curl, datachannel, mosquitto, or all)" ;;
esac

summary
