#!/usr/bin/env bash
# run_recorder_e2e.sh — End-to-end test for the StreamHub binary recorder.
#
# Data path:
#   FileReader(/tmp/udpstreamer_test_input.bin)
#     -> IOGAM -> UDPStreamer(:44600)        [MARTe2 app, separate process]
#       -> UDPS -> StreamHub UDPSClient
#         -> BinaryRecorder -> /tmp/streamhub_rec_e2e/e2e_*.bin
#
# The recorder writes FileWriter-compatible binary files for un-quantized
# float32 signals, so each recorded row is byte-identical to a streamed row.
# validate_binary.py confirms every non-zero recorded row matches an input row.
#
# Usage:  ./run_recorder_e2e.sh [--skip-build]
set -e

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(cd "${SCRIPT_DIR}/../../.." && pwd)"
TARGET=x86-linux
BUILD_DIR="${REPO_ROOT}/Build/${TARGET}"
OUT_DIR="${BUILD_DIR}/E2E/recorder"
mkdir -p "${OUT_DIR}"

VALIDATOR="${SCRIPT_DIR}/../datasources/validate_binary.py"
GEN_DATA="${SCRIPT_DIR}/../datasources/gen_test_data.py"
INPUT="/tmp/udpstreamer_test_input.bin"
REC_DIR="/tmp/streamhub_rec_e2e"

SKIP_BUILD=0
for arg in "$@"; do
    case "$arg" in
        --skip-build) SKIP_BUILD=1 ;;
        --help|-h) echo "Usage: $0 [--skip-build]"; exit 0 ;;
    esac
done

# ── Load environment ─────────────────────────────────────────────────────────
ENV_SCRIPT="${REPO_ROOT}/env.sh"
if [ ! -f "${ENV_SCRIPT}" ]; then
    echo "ERROR: ${ENV_SCRIPT} not found." >&2
    exit 1
fi
source "${ENV_SCRIPT}"

COMP="${MARTe2_Components_DIR}/Build/${TARGET}/Components"
export LD_LIBRARY_PATH="\
${BUILD_DIR}/Components/DataSources/UDPStreamer:\
${BUILD_DIR}/Components/Interfaces/UDPStream:\
${MARTe2_DIR}/Build/${TARGET}/Core:\
${COMP}/DataSources/LinuxTimer:\
${COMP}/DataSources/FileDataSource:\
${COMP}/GAMs/IOGAM:\
${LD_LIBRARY_PATH:-}"

MARTE_APP="${MARTe2_DIR}/Build/${TARGET}/App/MARTeApp.ex"
STREAMHUB_EX="${BUILD_DIR}/StreamHub/StreamHub.ex"

echo "=========================================="
echo " StreamHub Recorder E2E Test"
echo "=========================================="

# ── Step 1: Generate test data ───────────────────────────────────────────────
echo ""
echo "── Step 1: Generating test data ──"
python3 "${GEN_DATA}"

# ── Step 2: Build components ──────────────────────────────────────────────────
if [ "${SKIP_BUILD}" -eq 0 ]; then
    echo ""
    echo "── Step 2: Building components ──"
    make -C "${REPO_ROOT}/Source/Components/Interfaces/UDPStream" \
         -f Makefile.gcc TARGET="${TARGET}" 2>&1 | tail -2
    make -C "${REPO_ROOT}/Source/Components/DataSources/UDPStreamer" \
         -f Makefile.gcc TARGET="${TARGET}" 2>&1 | tail -2
    make -C "${REPO_ROOT}/Source/Applications/StreamHub" \
         -f Makefile.gcc TARGET="${TARGET}" 2>&1 | tail -2
fi

if [ ! -x "${MARTE_APP}" ]; then
    echo "ERROR: MARTeApp.ex not found at ${MARTE_APP}" >&2
    exit 1
fi
if [ ! -x "${STREAMHUB_EX}" ]; then
    echo "ERROR: StreamHub.ex not found at ${STREAMHUB_EX}" >&2
    exit 1
fi

# ── Step 3: Run the stack ─────────────────────────────────────────────────────
echo ""
echo "── Step 3: Running StreamHub + UDPStreamer ──"
rm -rf "${REC_DIR}"
mkdir -p "${REC_DIR}"

HUB_LOG="${OUT_DIR}/streamhub.log"
APP_LOG="${OUT_DIR}/marte.log"

# Start StreamHub first so it is ready to receive the CONFIG packet.
"${STREAMHUB_EX}" -cfg "${SCRIPT_DIR}/StreamHubRec.cfg" > "${HUB_LOG}" 2>&1 &
HUB_PID=$!
sleep 1

cleanup() {
    kill "${HUB_PID}" 2>/dev/null || true
    kill "${APP_PID}" 2>/dev/null || true
    wait "${HUB_PID}" 2>/dev/null || true
    wait "${APP_PID}" 2>/dev/null || true
}
trap cleanup EXIT

timeout 8 "${MARTE_APP}" -l RealTimeLoader -f "${SCRIPT_DIR}/RecorderStreamer.cfg" \
    -s Running > "${APP_LOG}" 2>&1 &
APP_PID=$!

# Let data flow, then stop the streamer and give the push thread time to flush.
sleep 7
kill "${APP_PID}" 2>/dev/null || true
wait "${APP_PID}" 2>/dev/null || true
sleep 2
kill "${HUB_PID}" 2>/dev/null || true
wait "${HUB_PID}" 2>/dev/null || true
trap - EXIT

echo "  Done. StreamHub log: ${HUB_LOG}"

# ── Step 4: Validate the recorded file ───────────────────────────────────────
echo ""
echo "── Step 4: Validating recorded output ──"
# The recorder names files <sourceId>_<UTCstamp>_<seq>.bin; pick the newest.
REC_FILE="$(ls -t "${REC_DIR}"/*.bin 2>/dev/null | head -1 || true)"
if [ -z "${REC_FILE}" ]; then
    echo "  ✗ FAIL: no recorded .bin file in ${REC_DIR}"
    echo "  --- StreamHub log tail ---"
    tail -20 "${HUB_LOG}" || true
    exit 1
fi
echo "  Recorded file: ${REC_FILE} ($(stat -c%s "${REC_FILE}") B)"

python3 "${VALIDATOR}" "${INPUT}" "${REC_FILE}" --label "recorder" \
    --json "${OUT_DIR}/recorder_e2e.json"

echo ""
echo "=========================================="
echo " Done — artifacts in ${OUT_DIR}"
echo "=========================================="
