#!/usr/bin/env bash
trap 'killm f' EXIT
#
# SPP CLA Loopback Test
#
# Tests that bundles can be sent and received via the SPP CLA using
# the loopback stub provider library.
#
# Copyright (c) 2025, California Institute of Technology.
# ALL RIGHTS RESERVED.  U.S. Government Sponsorship acknowledged.
#

# documentation boilerplate
CONFIGFILES=" \
./config/loopback.ionrc \
./config/loopback.bprc \
./config/loopback.ipnrc \
"
echo "########################################"
echo
pwd | sed "s/\/.*\///" | xargs echo "NAME: "
echo
echo "PURPOSE: Testing the SPP CLA with a loopback stub provider library."
echo
echo "CONFIG: Custom loopback configuration: "
echo
for N in $CONFIGFILES
do
    echo "$N:"
    cat $N
    echo "# EOF"
    echo
done
echo "OUTPUT: Uses bpsource and bpsink to send and receive a bundle via SPP."
echo
echo "########################################"

FAIL=0

# Find the stub library - check common locations
SRCDIR="${SRCDIR:-.}"
BUILDDIR="${BUILDDIR:-../..}"

# Try to find the library
if [ -f "${BUILDDIR}/bpv7/spp/stub/.libs/libspp_loopback_provider.so" ]; then
    STUBLIB="${BUILDDIR}/bpv7/spp/stub/.libs/libspp_loopback_provider.so"
elif [ -f "${BUILDDIR}/bpv7/spp/stub/.libs/libspp_loopback_provider.dylib" ]; then
    STUBLIB="${BUILDDIR}/bpv7/spp/stub/.libs/libspp_loopback_provider.dylib"
elif [ -f "${BUILDDIR}/.libs/libspp_loopback_provider.so" ]; then
    STUBLIB="${BUILDDIR}/.libs/libspp_loopback_provider.so"
elif [ -f "${BUILDDIR}/.libs/libspp_loopback_provider.dylib" ]; then
    STUBLIB="${BUILDDIR}/.libs/libspp_loopback_provider.dylib"
else
    echo "ERROR: Cannot find libspp_loopback_provider library."
    echo "Make sure to run 'make buildcheck' first to build the test libraries."
    exit 2
fi

echo "Using stub library: ${STUBLIB}"
STUBLIB=$(cd "$(dirname "$STUBLIB")" && pwd)/$(basename "$STUBLIB")
echo "Absolute path: ${STUBLIB}"

# SPP config: APID,seq_count,packet_type,sec_header_flag
SPP_CONFIG="123,0,0,0"

echo "Killing old ION..."
killm
# Kill any leftover SPP CLAs from previous runs (use SIGKILL to force)
pkill -9 -f "sppcli" 2>/dev/null
pkill -9 -f "sppclo" 2>/dev/null
./cleanup
sleep 1

# Clean up any old FIFO and generated config
rm -f /tmp/spp_loopback_fifo ion.log testfile1 testfile2

# Generate runtime bprc with actual library path
CONFIGDIR="./config"
sed -e "s|STUBLIB|${STUBLIB}|g" -e "s|SPP_CONFIG|${SPP_CONFIG}|g" \
    "${CONFIGDIR}/loopback.bprc" > "${CONFIGDIR}/loopback_runtime.bprc"

echo "Starting ION..."
ionadmin "${CONFIGDIR}/loopback.ionrc"
sleep 1
bpadmin "${CONFIGDIR}/loopback_runtime.bprc"
sleep 1

echo "Starting BP daemons (including SPP CLAs)..."
# Note: ipnadmin is run via 'r' command in loopbackstart.bprc before 's'
bpadmin "${CONFIGDIR}/loopbackstart.bprc"

# Wait for SPP CLAs to be running
echo "Waiting for SPP CLAs to start..."
for i in 1 2 3 4 5 6 7 8 9 10; do
    if pgrep -f "sppcli.*loopback" > /dev/null && pgrep -f "sppclo.*loopback" > /dev/null; then
        echo "SPP CLAs are running."
        break
    fi
    echo "  Waiting... ($i)"
    sleep 1
done
sleep 2

echo "Creating test file..."
echo "This is a test message for SPP loopback" > testfile1

echo "Starting bpsink..."
bpsink ipn:1.1 > testfile2 &
BPSINK_PID=$!
sleep 1

echo "Sending bundle via bpsource..."
echo "NOTE: The provider will report different sent/received byte counts."
echo "      Sent bytes include the 6-byte SPP header prepended by the provider."
echo "      Received bytes are bundle data only (SPP header is stripped)."
bpsource ipn:1.1 "This is a test message for SPP loopback"
sleep 3

echo "Checking received data..."
if grep -q "This is a test message for SPP loopback" testfile2; then
    echo "SUCCESS: Bundle received correctly via SPP loopback!"
else
    echo "ERROR: Bundle not received or content mismatch."
    echo "Expected: This is a test message for SPP loopback"
    echo "Received:"
    cat testfile2
    FAIL=1
fi

echo "Cleaning up..."
kill $BPSINK_PID 2>/dev/null
sleep 1

# Kill the SPP CLAs explicitly (use SIGKILL - they may be blocked on FIFO reads)
pkill -9 -f "sppcli" 2>/dev/null
pkill -9 -f "sppclo" 2>/dev/null
sleep 1

ionstop
sleep 1
killm

# Clean up
rm -f /tmp/spp_loopback_fifo testfile1 testfile2
rm -f "${CONFIGDIR}/loopback_runtime.bprc"

exit $FAIL
