#!/bin/sh

AUTOMERGE_FOUND=0
PKG_CFLAGS=""
PKG_LIBS=""

# Find compiler and export flags
CC=`"${R_HOME}/bin/R" CMD config CC`
CFLAGS=`"${R_HOME}/bin/R" CMD config CFLAGS`
LDFLAGS=`"${R_HOME}/bin/R" CMD config LDFLAGS`
export CC CFLAGS LDFLAGS

# Helper function: check for UTF-32 indexing in system library
check_utf32_indexing() {
    echo "#include <automerge-c/config.h>
    #ifndef AUTOMERGE_C_UTF32
    #error \"UTF-32 indexing is not enabled\"
    #endif
    int main(void) { return 0; }" | \
        ${CC} -I"$1" -xc - -c -o /dev/null 2>/dev/null
}

if [ "${AUTOMERGE_LIBS}" = "1" ]; then
    echo "AUTOMERGE_LIBS=1: forcing bundled source compilation"
else
    echo "Checking for system automerge installation..."

    for prefix in /usr/local /usr /opt/local /opt/homebrew; do
        if [ -f "${prefix}/include/automerge-c/automerge.h" ] && \
           [ -f "${prefix}/lib/libautomerge.a" ]; then
            echo "Found automerge in ${prefix}"

            # Check if it's built with UTF-32 indexing via compilation test
            if check_utf32_indexing "${prefix}/include"; then
                echo "Verified UTF-32 character indexing enabled"
                PKG_CFLAGS="-I${prefix}/include"
                PKG_LIBS="-L${prefix}/lib -lautomerge"
                AUTOMERGE_FOUND=1
                break
            else
                echo "Detected system automerge uses UTF-8 byte indexing"
                echo "This package requires UTF-32 character indexing for natural R semantics"
                echo "Will build from bundled source instead"
            fi
        fi
    done

    if [ ${AUTOMERGE_FOUND} -eq 0 ] && command -v pkg-config >/dev/null 2>&1; then
        if pkg-config --exists automerge-c 2>/dev/null; then
            echo "Found automerge via pkg-config"

            # Try to get the prefix from pkg-config
            prefix=$(pkg-config --variable=prefix automerge-c 2>/dev/null)
            if [ -n "${prefix}" ]; then
                if check_utf32_indexing "${prefix}/include"; then
                    echo "Verified UTF-32 character indexing enabled"
                    PKG_CFLAGS=$(pkg-config --cflags automerge-c)
                    PKG_LIBS=$(pkg-config --libs automerge-c)
                    AUTOMERGE_FOUND=1
                else
                    echo "Detected system automerge uses UTF-8 byte indexing"
                    echo "This package requires UTF-32 character indexing for natural R semantics"
                    echo "Will build from bundled source instead"
                fi
            fi
        fi
    fi
fi

if [ ${AUTOMERGE_FOUND} -eq 0 ]; then
    echo "System automerge not found, building from bundled source..."

    # Minimum Rust version required (MSRV)
    RUST_MSRV="1.85"

    # Check for Rust toolchain (cargo and rustc)
    # CRAN policy: check both system PATH and ~/.cargo/bin
    CARGO_CMD=""
    RUSTC_CMD=""

    # First check PATH
    if command -v cargo >/dev/null 2>&1; then
        CARGO_CMD="cargo"
    fi
    if command -v rustc >/dev/null 2>&1; then
        RUSTC_CMD="rustc"
    fi

    # Also check ~/.cargo/bin (rustup default location, often not on PATH)
    if [ -z "$CARGO_CMD" ] && [ -x "$HOME/.cargo/bin/cargo" ]; then
        CARGO_CMD="$HOME/.cargo/bin/cargo"
        export PATH="$HOME/.cargo/bin:$PATH"
    fi
    if [ -z "$RUSTC_CMD" ] && [ -x "$HOME/.cargo/bin/rustc" ]; then
        RUSTC_CMD="$HOME/.cargo/bin/rustc"
    fi

    # Verify both cargo and rustc are found
    if [ -z "$CARGO_CMD" ] || [ -z "$RUSTC_CMD" ]; then
        echo "-------------------- RUST TOOLCHAIN NOT FOUND --------------------"
        echo "This package requires Rust >= $RUST_MSRV to build from source."
        echo ""
        echo "Install Rust via your system package manager:"
        echo "  - Fedora/RHEL:   dnf install cargo"
        echo "  - Debian/Ubuntu: apt-get install cargo rustc"
        echo "  - macOS:         brew install rust"
        echo ""
        echo "Or install via rustup (recommended): https://rustup.rs/"
        echo ""
        echo "Alternatively, install automerge-c system-wide to skip Rust build."
        echo "------------------------------------------------------------------"
        exit 1
    fi

    # Check Rust version meets minimum requirement
    RUST_VERSION=$($RUSTC_CMD --version | sed -n 's/rustc \([0-9]*\.[0-9]*\.[0-9]*\).*/\1/p')
    RUST_MAJOR=$(echo $RUST_VERSION | cut -d. -f1)
    RUST_MINOR=$(echo $RUST_VERSION | cut -d. -f2)
    MSRV_MAJOR=$(echo $RUST_MSRV | cut -d. -f1)
    MSRV_MINOR=$(echo $RUST_MSRV | cut -d. -f2)

    if [ "$RUST_MAJOR" -lt "$MSRV_MAJOR" ] || \
       { [ "$RUST_MAJOR" -eq "$MSRV_MAJOR" ] && [ "$RUST_MINOR" -lt "$MSRV_MINOR" ]; }; then
        echo "-------------------- RUST VERSION TOO OLD --------------------"
        echo "Found Rust $RUST_VERSION but this package requires Rust >= $RUST_MSRV"
        echo ""
        echo "Update Rust via your package manager or rustup:"
        echo "  - Fedora/RHEL:   dnf update cargo"
        echo "  - Debian/Ubuntu: apt-get update && apt-get upgrade cargo rustc"
        echo "  - macOS:         brew upgrade rust"
        echo "  - rustup:        rustup update stable"
        echo "---------------------------------------------------------------"
        exit 1
    fi

    echo "Building automerge-c from bundled source..."
    echo "using Rust package manager: '$($CARGO_CMD --version)'"
    echo "using Rust compiler: '$($RUSTC_CMD --version)'"

    rm -rf am-build am-install

    # Set TMPDIR to avoid rustix test file warning in R CMD check
    export TMPDIR="${PWD}/am-build/tmp"
    mkdir -p "$TMPDIR"

    # Set CARGO_HOME to prevent writes to ~/.cargo (CRAN policy)
    export CARGO_HOME="${PWD}/am-build/.cargo"
    mkdir -p "$CARGO_HOME"

    # Keep Cargo's build artefacts inside the package build tree
    export CARGO_TARGET_DIR="${PWD}/am-build/target"

    # automerge-c's build.rs writes the cbindgen-generated header here
    export CBINDGEN_TARGET_DIR="${PWD}/am-install/include/automerge-c"
    mkdir -p "$CBINDGEN_TARGET_DIR" am-install/lib

    # Generate vendor config with absolute path (env vars don't work for source replacement)
    cat > "$CARGO_HOME/config.toml" << EOF
[source.crates-io]
replace-with = "vendored-sources"

[source.vendored-sources]
directory = "${PWD}/src/automerge/rust/vendor"
EOF

    # Extract vendored Rust dependencies
    if [ -f "src/automerge/rust/vendor.tar.xz" ] && [ ! -d "src/automerge/rust/vendor" ]; then
        echo "Extracting vendored Rust dependencies..."
        xz -dc src/automerge/rust/vendor.tar.xz | tar -xf - -C src/automerge/rust
    fi

    echo "Building (this may take several minutes)..."
    # Default features select UTF-32 indexing; -j2 respects CRAN's core limit.
    # build.rs runs cbindgen to emit ${CBINDGEN_TARGET_DIR}/automerge.h.
    "$CARGO_CMD" build --release -j2 \
        --manifest-path src/automerge/rust/automerge-c/Cargo.toml \
        || { echo "ERROR: cargo build failed"; exit 1; }

    HEADER="am-install/include/automerge-c/automerge.h"
    if [ ! -f "$HEADER" ]; then
        echo "ERROR: cbindgen did not generate ${HEADER}"
        exit 1
    fi

    # Post-process the cbindgen header (work previously done by CMake):
    #   1. cbindgen renders consecutive capitals as "A_M..."; restore "AM_...".
    #   2. cbindgen ignores size_of::<usize>(); substitute the pointer size.
    PTR_SIZE=`"${R_HOME}/bin/Rscript" -e 'cat(.Machine$sizeof.pointer)'`
    sed -e 's/A_M\([^_][^_]*\)_/AM_\1_/g' \
        -e "s/USIZE_/+${PTR_SIZE}/g" \
        "$HEADER" > "${HEADER}.tmp" && mv "${HEADER}.tmp" "$HEADER"

    # Stage the static library where Makevars expects it
    cp am-build/target/release/libautomerge_core.a am-install/lib/libautomerge.a \
        || { echo "ERROR: failed to stage static library"; exit 1; }

    rm -rf am-build

    echo "Successfully built automerge-c from source"

    PKG_CFLAGS="-I../am-install/include"
    PKG_LIBS="../am-install/lib/libautomerge.a -pthread"
fi

case "$(uname -s)" in
    Darwin*)
        PKG_LIBS="${PKG_LIBS} -framework Security -framework Foundation"
        ;;
    Linux*)
        PKG_LIBS="${PKG_LIBS} -ldl -lm -lrt"
        ;;
esac

echo "Configuration:"
echo "  PKG_CFLAGS: ${PKG_CFLAGS}"
echo "  PKG_LIBS: ${PKG_LIBS}"

sed -e "s|@PKG_CFLAGS@|${PKG_CFLAGS}|" \
    -e "s|@PKG_LIBS@|${PKG_LIBS}|" \
    src/Makevars.in > src/Makevars

exit 0
