#!/usr/bin/env bash
# run.sh – Build UDPStreamer and launch the test MARTe2 application.
#
# Usage:
#   ./run.sh              # run MARTe2 app only
#   ./run.sh --webui      # also start the WebUI Go client in the background
#   ./run.sh --nativeui   # also start the NativeUI ImGui client in the background
#   ./run.sh --qtui       # also start the NativeUI Qt client in the background
#   ./run.sh --help       # show this message
#
# The clients are started with three sources:
#   Streamer        @ 127.0.0.1:44500  (scalar signals,  PacketTime, 1 kHz)
#   FastStreamer    @ 127.0.0.1:44501  (packed arrays,   FirstSample/LastSample, 5 kHz)
#   FullArrStreamer @ 127.0.0.1:44502  (packed arrays,   FullArray, 5 kHz)
#
# Prerequisites:
#   - marte_env.sh must be present in the repo root (sets MARTe2_DIR, etc.)
#   - MARTe2 and MARTe2-components must already be built
#
# The script resolves all paths relative to the repo root so it can be
# called from any working directory.

set -e

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(cd "${SCRIPT_DIR}/../.." && pwd)"

# ── Parse arguments ──────────────────────────────────────────────────────────
START_WEBUI=0
START_NATIVEUI=0
START_QTUI=0
for arg in "$@"; do
    case "$arg" in
        --webui)     START_WEBUI=1 ;;
        --nativeui)  START_NATIVEUI=1 ;;
        --qtui)      START_QTUI=1 ;;
        --help|-h)
            sed -n '2,21p' "$0"
            exit 0
            ;;
    esac
done

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

if [ -z "${MARTe2_DIR}" ]; then
    echo "ERROR: MARTe2_DIR is not set after sourcing marte_env.sh." >&2
    exit 1
fi

# ── Build components ─────────────────────────────────────────────────────────
TARGET=x86-linux
UDPSTREAMER_SRC="${REPO_ROOT}/Source/Components/DataSources/UDPStreamer"
UDPSTREAMER_LIB="${REPO_ROOT}/Build/${TARGET}/Components/DataSources/UDPStreamer"
SINEARRAYGAM_SRC="${REPO_ROOT}/Source/Components/GAMs/SineArrayGAM"
SINEARRAYGAM_LIB="${REPO_ROOT}/Build/${TARGET}/Components/GAMs/SineArrayGAM"
TIMEARRAYGAM_SRC="${REPO_ROOT}/Source/Components/GAMs/TimeArrayGAM"
TIMEARRAYGAM_LIB="${REPO_ROOT}/Build/${TARGET}/Components/GAMs/TimeArrayGAM"

echo "==> Building UDPStreamer (TARGET=${TARGET})..."
make -C "${UDPSTREAMER_SRC}" \
     -f Makefile.gcc \
     TARGET="${TARGET}" \
     2>&1 | tail -5

echo "==> Building SineArrayGAM (TARGET=${TARGET})..."
make -C "${SINEARRAYGAM_SRC}" \
     -f Makefile.gcc \
     TARGET="${TARGET}" \
     2>&1 | tail -5

echo "==> Building TimeArrayGAM (TARGET=${TARGET})..."
make -C "${TIMEARRAYGAM_SRC}" \
     -f Makefile.gcc \
     TARGET="${TARGET}" \
     2>&1 | tail -5
echo "==> Build done."

# ── Build WebUI binary (if requested and not already built) ──────────────────
WEBUI_DIR="${REPO_ROOT}/Client/WebUI"
WEBUI_BIN="${WEBUI_DIR}/udpstreamer-webui"
if [ "${START_WEBUI}" -eq 1 ] && [ ! -x "${WEBUI_BIN}" ]; then
    echo "==> Building WebUI..."
    (cd "${WEBUI_DIR}" && go build -o udpstreamer-webui ./...)
    echo "==> WebUI build done."
fi

# ── Build NativeUI (ImGui) binary (if requested and not already built) ───────
NATIVEUI_DIR="${REPO_ROOT}/Client/NativeUI"
NATIVEUI_BUILD="${NATIVEUI_DIR}/build"
NATIVEUI_BIN="${NATIVEUI_BUILD}/daq_viewer"
if [ "${START_NATIVEUI}" -eq 1 ]; then
    if [ ! -x "${NATIVEUI_BIN}" ]; then
        echo "==> Building NativeUI/ImGui (cmake)..."
        cmake -S "${NATIVEUI_DIR}" -B "${NATIVEUI_BUILD}" -DCMAKE_BUILD_TYPE=Release -Wno-dev
        cmake --build "${NATIVEUI_BUILD}" --parallel "$(nproc)"
        echo "==> NativeUI/ImGui build done."
    else
        # Rebuild if sources are newer than the binary
        if find "${NATIVEUI_DIR}/src" -name '*.cpp' -o -name '*.h' \
                | xargs ls -t 2>/dev/null | head -1 \
                | xargs -I{} test {} -nt "${NATIVEUI_BIN}" 2>/dev/null; then
            echo "==> Sources changed — rebuilding NativeUI/ImGui..."
            cmake --build "${NATIVEUI_BUILD}" --parallel "$(nproc)"
            echo "==> NativeUI/ImGui rebuild done."
        fi
    fi
fi

# ── Build NativeUI-Qt binary (if requested and not already built) ─────────────
QTUI_DIR="${REPO_ROOT}/Client/NativeUI-Qt"
QTUI_BUILD="${QTUI_DIR}/build"
QTUI_BIN="${QTUI_BUILD}/daq_viewer"
if [ "${START_QTUI}" -eq 1 ]; then
    if [ ! -x "${QTUI_BIN}" ]; then
        echo "==> Building NativeUI/Qt (cmake)..."
        cmake -S "${QTUI_DIR}" -B "${QTUI_BUILD}" -DCMAKE_BUILD_TYPE=Release -Wno-dev
        cmake --build "${QTUI_BUILD}" --parallel "$(nproc)"
        echo "==> NativeUI/Qt build done."
    else
        # Rebuild if sources are newer than the binary
        if find "${QTUI_DIR}/src" "${REPO_ROOT}/Client/NativeUI/src" \
                \( -name '*.cpp' -o -name '*.h' \) \
                | xargs ls -t 2>/dev/null | head -1 \
                | xargs -I{} test {} -nt "${QTUI_BIN}" 2>/dev/null; then
            echo "==> Sources changed — rebuilding NativeUI/Qt..."
            cmake --build "${QTUI_BUILD}" --parallel "$(nproc)"
            echo "==> NativeUI/Qt rebuild done."
        fi
    fi
fi

# ── Set LD_LIBRARY_PATH ───────────────────────────────────────────────────────
COMP="${MARTe2_Components_DIR}/Build/${TARGET}/Components"

export LD_LIBRARY_PATH="\
${UDPSTREAMER_LIB}:\
${SINEARRAYGAM_LIB}:\
${TIMEARRAYGAM_LIB}:\
${MARTe2_DIR}/Build/${TARGET}/Core:\
${COMP}/DataSources/LinuxTimer:\
${COMP}/DataSources/LoggerDataSource:\
${COMP}/GAMs/IOGAM:\
${COMP}/GAMs/WaveformGAM:\
${LD_LIBRARY_PATH}"

echo "==> LD_LIBRARY_PATH=${LD_LIBRARY_PATH}"

# ── Create class-name symlinks for MARTe2 auto-loader ────────────────────────
WAVEFORM_DIR="${COMP}/GAMs/WaveformGAM"
for cls in WaveformSin WaveformChirp WaveformPointsDef; do
    target="${WAVEFORM_DIR}/${cls}.so"
    if [ ! -e "${target}" ]; then
        ln -sf "${WAVEFORM_DIR}/WaveformGAM.so" "${target}"
    fi
done

# ── Optionally start WebUI ────────────────────────────────────────────────────
WEBUI_PID=""
if [ "${START_WEBUI}" -eq 1 ]; then
    echo "==> Starting WebUI on http://localhost:8080..."
    "${WEBUI_BIN}" \
        --source "Streamer@127.0.0.1:44500/239.0.0.1:44503" \
        --source "FastStreamer@127.0.0.1:44501" \
        --source "FullArrStreamer@127.0.0.1:44502" \
        --listen :8080 &
    WEBUI_PID=$!
    echo "==> WebUI PID ${WEBUI_PID}"
fi

# ── Optionally start NativeUI (ImGui) ────────────────────────────────────────
NATIVEUI_PID=""
if [ "${START_NATIVEUI}" -eq 1 ]; then
    if [ ! -x "${NATIVEUI_BIN}" ]; then
        echo "ERROR: NativeUI/ImGui binary not found at ${NATIVEUI_BIN}" >&2
        exit 1
    fi
    echo "==> Starting NativeUI/ImGui..."
    "${NATIVEUI_BIN}" \
        "Streamer@127.0.0.1:44500" \
        "FastStreamer@127.0.0.1:44501" \
        "FullArrStreamer@127.0.0.1:44502" &
    NATIVEUI_PID=$!
    echo "==> NativeUI/ImGui PID ${NATIVEUI_PID}"
fi

# ── Optionally start NativeUI-Qt ──────────────────────────────────────────────
QTUI_PID=""
if [ "${START_QTUI}" -eq 1 ]; then
    if [ ! -x "${QTUI_BIN}" ]; then
        echo "ERROR: NativeUI/Qt binary not found at ${QTUI_BIN}" >&2
        exit 1
    fi
    echo "==> Starting NativeUI/Qt..."
    "${QTUI_BIN}" \
        "Streamer@127.0.0.1:44500" \
        "FastStreamer@127.0.0.1:44501" \
        "FullArrStreamer@127.0.0.1:44502" &
    QTUI_PID=$!
    echo "==> NativeUI/Qt PID ${QTUI_PID}"
fi

# ── Launch MARTe2 application ─────────────────────────────────────────────────
MARTE_APP="${MARTe2_DIR}/Build/${TARGET}/App/MARTeApp.ex"
CFG="${SCRIPT_DIR}/TestApp.cfg"

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

echo "==> Starting MARTe2 application (state=Running)..."
echo "==>   Thread1: scalar signals     1 kHz  → port 44500"
echo "==>   Thread2: packed arrays      5 kHz  → port 44501 (FirstSample / LastSample)"
echo "==>   Thread3: FullArray arrays   5 kHz  → port 44502 (FullArray)"
echo "==> Press Ctrl+C to stop."
echo ""

cleanup() {
    echo ""
    echo "==> Stopping..."
    [ -n "${WEBUI_PID}"    ] && kill -0 "${WEBUI_PID}"    2>/dev/null && kill "${WEBUI_PID}"
    [ -n "${NATIVEUI_PID}" ] && kill -0 "${NATIVEUI_PID}" 2>/dev/null && kill "${NATIVEUI_PID}"
    [ -n "${QTUI_PID}"     ] && kill -0 "${QTUI_PID}"     2>/dev/null && kill "${QTUI_PID}"
}
trap cleanup EXIT INT TERM

"${MARTE_APP}" \
    -l RealTimeLoader \
    -f "${CFG}" \
    -s Running
