#!/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 (softIoc binary available in PATH or EPICS_BASE)
#   • uopi built (script builds it if missing)
#
# uopi connects to EPICS via its built-in pure-Go CA client — no libca needed.
# Set UOPI_CA_DEBUG=1 (default below) to enable CA-level debug logging.

set -euo pipefail

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

# ── Locate EPICS tools ────────────────────────────────────────────────────────

# If EPICS_BASE is set, add its bin directory to PATH automatically.
if [ -n "${EPICS_BASE:-}" ]; then
    if [ -z "${EPICS_ARCH:-}" ]; then
        EPICS_ARCH="$(ls "$EPICS_BASE/bin" 2>/dev/null | grep -i linux | head -1 || true)"
        EPICS_ARCH="${EPICS_ARCH:-linux-x86_64}"
    fi
    export PATH="$EPICS_BASE/bin/$EPICS_ARCH:$PATH"
    echo "EPICS_BASE=$EPICS_BASE  EPICS_ARCH=$EPICS_ARCH"
fi

if ! command -v softIoc &>/dev/null; then
    echo "ERROR: softIoc not found in PATH."
    echo "  Set EPICS_BASE=/path/to/epics/base, or add softIoc to your PATH."
    exit 1
fi
echo "softIoc: $(command -v softIoc)"

# ── 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"

# Enable CA-level debug logging in uopi (set to "" to disable).
export UOPI_CA_DEBUG="${UOPI_CA_DEBUG:-1}"

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

echo "Building uopi + catools..."
cd "$PROJECT_ROOT"
make backend 2>&1
echo ""
echo "  catools: $PROJECT_ROOT/dist/catools"
echo "  Usage:   dist/catools caget UOPI:TICK"
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.5

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

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

# Wait for the IOC to start listening on TCP 5064 (up to 10 s).
# We probe with nc (netcat) first — no EPICS tools required.
echo -n "Waiting for IOC port 5064"
IOC_READY=0
for i in $(seq 1 20); do
    if nc -z 127.0.0.1 5064 2>/dev/null; then
        echo " OK (TCP 5064 open)"
        IOC_READY=1
        break
    fi
    echo -n "."
    sleep 0.5
done

if [ "$IOC_READY" -eq 0 ]; then
    echo ""
    echo "ERROR: IOC port 5064 not open after 10 seconds."
    echo "softIoc log:"
    cat "$WORKSPACE/softioc.log" || true
    exit 1
fi

# Optional deeper check with caget if it's available.
if command -v caget &>/dev/null; then
    echo -n "Verifying UOPI:TICK with caget"
    for i in $(seq 1 10); do
        if caget -w 1 UOPI:TICK >/dev/null 2>&1; then
            echo " OK"
            break
        fi
        echo -n "."
        sleep 0.5
        if [ "$i" -eq 10 ]; then
            echo " (timeout — continuing anyway)"
        fi
    done
else
    echo "caget not in PATH — skipping PV check (softIoc assumed ready)"
    sleep 1
fi

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

echo ""
echo "Starting uopi (http://localhost:8088)..."
echo "  UOPI_CA_DEBUG=$UOPI_CA_DEBUG"
echo "  Config: $WORKSPACE/uopi.toml"
echo "  Log will appear below. Press Ctrl-C to stop."
echo ""

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