#!/bin/sh
# configure - builds arduino_driver_c (extras/c_api) as a static archive via
# CMake, then writes src/Makevars so R links it straight into this
# package's single shared object.
#
# R always stages a package into an isolated temp directory before running
# configure (true for R CMD INSTALL on a directory or a tarball, and for
# remotes::install_github()), so this script cannot rely on its own
# checkout having its monorepo siblings (extras/c_api, extras/driver) on
# disk next to it. It resolves a source for extras/c_api in one of two ways:
#   1. $ARDUINODRIVER_LOCAL_CHECKOUT, if set: a local ArduinoDriver checkout
#      to build against directly (fast, no network -- for developing this
#      package inside the monorepo, e.g. via `R CMD INSTALL extras/r/
#      arduinodriver` run with that variable exported).
#   2. Otherwise, a CMake FetchContent of the ArduinoDriver repo itself, at
#      $ARDUINODRIVER_GIT_TAG (default: main; the MADS ArduinoIO_plugin
#      pins a release tag the same way once one exists -- see its
#      CMakeLists.txt -- update the default below to match once this
#      package's own version has a matching git tag).
set -e

PKG_ROOT=$(cd "$(dirname "$0")" && pwd)
BUILD_DIR="$PKG_ROOT/src/native-build"
GIT_TAG=${ARDUINODRIVER_GIT_TAG:-main}

CMAKE=$(command -v cmake || true)
if [ -z "$CMAKE" ]; then
  echo "configure: cmake not found on PATH; it is required to build arduino_driver_c." >&2
  exit 1
fi

if [ -n "$ARDUINODRIVER_LOCAL_CHECKOUT" ] && [ -f "$ARDUINODRIVER_LOCAL_CHECKOUT/extras/c_api/CMakeLists.txt" ]; then
  echo "configure: using local checkout at $ARDUINODRIVER_LOCAL_CHECKOUT"
  CMAKE_SOURCE_DIR="$ARDUINODRIVER_LOCAL_CHECKOUT/extras/c_api"
else
  echo "configure: fetching ArduinoDriver (git tag $GIT_TAG) via CMake FetchContent..."
  FETCH_DIR="$PKG_ROOT/src/native-fetch"
  mkdir -p "$FETCH_DIR"
  cat > "$FETCH_DIR/CMakeLists.txt" <<EOF
cmake_minimum_required(VERSION 3.24)
project(ArduinoDriverRFetch LANGUAGES NONE)
include(FetchContent)
FetchContent_Declare(arduinodriver_upstream
  GIT_REPOSITORY https://github.com/pbosetti/ArduinoDriver.git
  GIT_TAG $GIT_TAG
  GIT_SHALLOW TRUE)
FetchContent_MakeAvailable(arduinodriver_upstream)
add_subdirectory("\${arduinodriver_upstream_SOURCE_DIR}/extras/c_api" "\${CMAKE_CURRENT_BINARY_DIR}/c_api")
EOF
  CMAKE_SOURCE_DIR="$FETCH_DIR"
fi

"$CMAKE" -S "$CMAKE_SOURCE_DIR" -B "$BUILD_DIR" \
  -DCMAKE_BUILD_TYPE=Release \
  -DCMAKE_POSITION_INDEPENDENT_CODE=ON \
  -DARDUINODRIVER_C_API_SHARED=OFF \
  -DLIBUSB_ENABLE_UDEV=OFF \
  -DARDUINODRIVER_C_API_BUILD_TESTS=OFF \
  -DARDUINODRIVER_C_API_INSTALL=OFF \
  -DARDUINODRIVER_BUILD_CLI=OFF
"$CMAKE" --build "$BUILD_DIR" --target arduino_driver_c --config Release

find_one() {
  # First match under BUILD_DIR (and, for a source file like the public
  # header, under CMAKE_SOURCE_DIR too -- in local-checkout mode that is
  # extras/c_api itself, outside BUILD_DIR entirely). The caller checks for
  # an empty result.
  find "$BUILD_DIR" "$CMAKE_SOURCE_DIR" -name "$1" -print -quit 2>/dev/null
}

ARDUINO_DRIVER_C_LIB=$(find_one libarduino_driver_c.a)
ARDUINO_DRIVER_LIB=$(find_one libarduino_driver.a)
FMT_LIB=$(find_one libfmt.a)
LIBUSB_LIB=$(find_one libusb-1.0.a)
HEADER=$(find_one arduino_driver_c.h)
EXPORT_HEADER=$(find_one adrv_export.h)

for name in ARDUINO_DRIVER_C_LIB ARDUINO_DRIVER_LIB FMT_LIB LIBUSB_LIB HEADER EXPORT_HEADER; do
  eval "value=\$$name"
  if [ -z "$value" ]; then
    echo "configure: could not find the built $name under $BUILD_DIR" >&2
    exit 1
  fi
done

HEADER_DIR=$(dirname "$HEADER")
EXPORT_HEADER_DIR=$(dirname "$EXPORT_HEADER")

# No -ludev on Linux: the CMake invocation above builds libusb with
# LIBUSB_ENABLE_UDEV=OFF, so the package needs neither libudev headers at
# build time nor libudev.so.1 at run time (libusb uses its netlink hotplug
# path instead; device enumeration is unaffected).
EXTRA_LIBS=""
case "$(uname -s)" in
  Darwin) EXTRA_LIBS="-framework Foundation -framework IOKit -framework Security" ;;
  Linux) EXTRA_LIBS="-lpthread -lrt" ;;
esac

cat > "$PKG_ROOT/src/Makevars" <<EOF
# Generated by configure; see configure for how these paths were found.
PKG_CPPFLAGS = -I$HEADER_DIR -I$EXPORT_HEADER_DIR
PKG_LIBS = $ARDUINO_DRIVER_C_LIB $ARDUINO_DRIVER_LIB $FMT_LIB $LIBUSB_LIB $EXTRA_LIBS
CXX_STD = CXX20
EOF

echo "configure: wrote $PKG_ROOT/src/Makevars"
exit 0
