#!/usr/bin/env bash
# workspace/run.sh — start softIOC + uopi for EPICS workspace testing
#
# Usage (from project root):
#   bash workspace/run.sh
#
# Requirements:
#   • EPICS Base installed (EPICS_BASE set, or auto-detected below)
#   • softIoc binary available
#   • uopi built with EPICS support (script builds it if missing)

set -euo pipefail

PROJECT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
WORKSPACE="$PROJECT_ROOT/workspace"
BINARY="$PROJECT_ROOT/dist/uopi"

# ── Locate EPICS Base ─────────────────────────────────────────────────────────

if [ -z "${EPICS_BASE:-}" ]; then
    for candidate in \
        /usr/lib/epics \
        /usr/local/epics \
        /opt/epics/base \
        /opt/epics; do
        if [ -f "$candidate/include/cadef.h" ]; then
            export EPICS_BASE="$candidate"
            break
        fi
    done
fi

if [ -z "${EPICS_BASE:-}" ]; then
    echo "ERROR: EPICS_BASE is not set and could not be auto-detected."
    echo "  export EPICS_BASE=/path/to/epics/base"
    exit 1
fi

# Detect architecture
EPICS_ARCH="${EPICS_ARCH:-$(ls "$EPICS_BASE/lib" | grep linux | head -1)}"
if [ -z "$EPICS_ARCH" ]; then
    EPICS_ARCH="linux-x86_64"
fi

# ── Environment ───────────────────────────────────────────────────────────────

# Point CA exclusively at the local IOC — no broadcast scanning.
export EPICS_CA_ADDR_LIST="127.0.0.1"
export EPICS_CA_AUTO_ADDR_LIST="NO"

# Ensure the EPICS shared libraries are found at runtime.
export LD_LIBRARY_PATH="$EPICS_BASE/lib/$EPICS_ARCH${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}"

# Make EPICS tools (softIoc, caget, caput…) available.
export PATH="$EPICS_BASE/bin/$EPICS_ARCH:$PATH"

# ── Locate softIoc ────────────────────────────────────────────────────────────

if ! command -v softIoc &>/dev/null; then
    echo "ERROR: softIoc not found in $EPICS_BASE/bin/$EPICS_ARCH or PATH."
    exit 1
fi

# ── Build uopi ────────────────────────────────────────────────────────────────

echo "Building uopi with EPICS support..."
cd "$PROJECT_ROOT"
make backend-epics 2>&1
echo ""

# ── Cleanup handler ───────────────────────────────────────────────────────────

PIDS=()
cleanup() {
    echo ""
    echo "Shutting down..."
    for pid in "${PIDS[@]:-}"; do
        kill "$pid" 2>/dev/null || true
    done
    wait 2>/dev/null || true
}
trap cleanup EXIT INT TERM

# ── Kill any stale softIOC from a previous run ────────────────────────────────

pkill -x softIoc 2>/dev/null || true
# Give the OS a moment to release the CA port (5064/tcp+udp).
sleep 0.3

# ── Start softIOC ─────────────────────────────────────────────────────────────

echo "Starting softIOC..."
softIoc -S -d "$WORKSPACE/softioc/uopi_test.db" \
    >"$WORKSPACE/softioc.log" 2>&1 &
IOC_PID=$!
PIDS+=("$IOC_PID")

# Wait for the IOC to accept Channel Access connections (up to 10 s).
echo -n "Waiting for IOC to be ready"
for i in $(seq 1 20); do
    if caget -w 1 UOPI:TICK >/dev/null 2>&1; then
        echo " OK"
        break
    fi
    echo -n "."
    sleep 0.5
    if [ "$i" -eq 20 ]; then
        echo ""
        echo "ERROR: IOC did not become ready within 10 seconds."
        echo "Check $WORKSPACE/softioc.log for details."
        exit 1
    fi
done

# ── Start uopi ────────────────────────────────────────────────────────────────

echo "Starting uopi (http://localhost:8080)..."
echo "  Open the browser, switch to Edit mode, load workspace/data/epics_test.xml"
echo "  or select it from the interface list in View mode."
echo "  Press Ctrl-C to stop."
echo ""

cd "$PROJECT_ROOT"
"$BINARY" -config "$WORKSPACE/uopi.toml"
