#!/bin/bash

ARDOP_DIR="$HOME/repos/ardop"
ARDOP_EXE="$ARDOP_DIR/build/macos/ardopcf"

CAT_PORT="/dev/cu.usbserial-00F490390"
PTT_PORT="/dev/cu.usbserial-00F490391"

GPS_PTY="$HOME/corelocation-gps"
GPS_FEED="$HOME/corelocation-gps-feed"
GPS_NMEA="$HOME/bin/corelocation-nmea"

GPSD_PORT=2947
RIGCTLD_PORT=4532
ARDOP_PORT=8515
ARDOP_WEB_PORT=8514
PAT_PORT=8080

LOGDIR="$HOME/winlink-launcher-logs"
mkdir -p "$LOGDIR"

timestamp() {
    date "+%Y-%m-%d %H:%M:%S"
}

log() {
    echo "[$(timestamp)] $*"
}

port_open() {
    nc -z 127.0.0.1 "$1" >/dev/null 2>&1
}

wait_for_port() {
    local port="$1"
    local name="$2"
    local count=0

    while [ "$count" -lt 40 ]; do
        if port_open "$port"; then
            log "$name is ready on port $port."
            return 0
        fi
        sleep 0.5
        count=$((count + 1))
    done

    log "ERROR: $name did not become ready on port $port."
    return 1
}

wait_for_file() {
    local path="$1"
    local name="$2"
    local count=0

    while [ "$count" -lt 20 ]; do
        if [ -e "$path" ]; then
            log "$name is ready."
            return 0
        fi
        sleep 0.25
        count=$((count + 1))
    done

    log "ERROR: $name did not appear."
    return 1
}

notify() {
    osascript -e "display notification \"$1\" with title \"Winlink ARDOP\"" \
        >/dev/null 2>&1
}

echo
echo "============================================================"
echo "             VE3ZDN WINLINK / ARDOP STARTUP"
echo "============================================================"
echo

# ------------------------------------------------------------
# Required software
# ------------------------------------------------------------

log "Checking required software..."

for cmd in \
    rigctld \
    rigctl \
    pat \
    nc \
    socat \
    gpsd \
    gpspipe \
    CoreLocationCLI
do
    if ! command -v "$cmd" >/dev/null 2>&1; then
        log "ERROR: Cannot find '$cmd' in PATH."
        notify "Startup failed: missing $cmd"
        exit 1
    fi
done

if [ ! -x "$ARDOP_EXE" ]; then
    log "ERROR: ardopcf not found:"
    log "       $ARDOP_EXE"
    exit 1
fi

if [ ! -x "$GPS_NMEA" ]; then
    log "ERROR: Core Location NMEA bridge not found:"
    log "       $GPS_NMEA"
    exit 1
fi

if [ ! -e "$CAT_PORT" ]; then
    log "ERROR: FTdx10 Enhanced CAT port not found:"
    log "       $CAT_PORT"
    exit 1
fi

if [ ! -e "$PTT_PORT" ]; then
    log "ERROR: FTdx10 Standard PTT port not found:"
    log "       $PTT_PORT"
    exit 1
fi

log "Required software and FTdx10 serial ports found."

# ------------------------------------------------------------
# GPS: socat pseudo-terminal pair
# ------------------------------------------------------------

if port_open "$GPSD_PORT"; then
    log "gpsd is already listening on port $GPSD_PORT."
else
    log "Starting Core Location GPS stack..."

    # Remove stale symlinks from any previous run.
    rm -f "$GPS_PTY" "$GPS_FEED"

    nohup socat \
        pty,raw,echo=0,link="$GPS_PTY" \
        pty,raw,echo=0,link="$GPS_FEED" \
        >"$LOGDIR/socat-gps.log" 2>&1 &

    echo $! > "$LOGDIR/socat-gps.pid"

    if ! wait_for_file "$GPS_PTY" "GPS input PTY"; then
        tail -30 "$LOGDIR/socat-gps.log"
        notify "Startup failed: GPS PTY unavailable"
        exit 1
    fi

    if ! wait_for_file "$GPS_FEED" "GPS feed PTY"; then
        tail -30 "$LOGDIR/socat-gps.log"
        notify "Startup failed: GPS feed unavailable"
        exit 1
    fi

    # --------------------------------------------------------
    # Core Location -> NMEA
    # --------------------------------------------------------

    log "Starting Core Location NMEA feed..."

    nohup "$GPS_NMEA" \
        >"$GPS_FEED" \
        2>"$LOGDIR/corelocation-nmea.log" &

    echo $! > "$LOGDIR/corelocation-nmea.pid"

    sleep 1

    if ! kill -0 "$(cat "$LOGDIR/corelocation-nmea.pid")" 2>/dev/null; then
        log "ERROR: Core Location NMEA bridge exited."
        tail -30 "$LOGDIR/corelocation-nmea.log"
        notify "Startup failed: GPS location feed"
        exit 1
    fi

    # --------------------------------------------------------
    # Real gpsd
    # --------------------------------------------------------

    log "Starting gpsd..."

    nohup gpsd \
        -N \
        -n \
        -S "$GPSD_PORT" \
        "$GPS_PTY" \
        >"$LOGDIR/gpsd.log" 2>&1 &

    echo $! > "$LOGDIR/gpsd.pid"

    if ! wait_for_port "$GPSD_PORT" "gpsd"; then
        tail -40 "$LOGDIR/gpsd.log"
        notify "Startup failed: gpsd did not respond"
        exit 1
    fi

    # Give gpsd a moment to consume an NMEA fix.
    sleep 2
fi

# ------------------------------------------------------------
# rigctld — direct Hamlib control of FTdx10 Enhanced COM port
# ------------------------------------------------------------

if port_open "$RIGCTLD_PORT"; then
    log "rigctld is already listening on port $RIGCTLD_PORT."
else
    log "Starting rigctld..."

    nohup rigctld \
        -m 1042 \
        -r "$CAT_PORT" \
        -s 38400 \
        -T 127.0.0.1 \
        -t "$RIGCTLD_PORT" \
        >"$LOGDIR/rigctld.log" 2>&1 &

    echo $! > "$LOGDIR/rigctld.pid"

    if ! wait_for_port "$RIGCTLD_PORT" "rigctld"; then
        tail -30 "$LOGDIR/rigctld.log"
        notify "Startup failed: rigctld did not respond"
        exit 1
    fi
fi

# ------------------------------------------------------------
# CAT check
# ------------------------------------------------------------

log "Testing direct CAT path to FTdx10..."

FREQ=$(rigctl -m 2 -r 127.0.0.1:"$RIGCTLD_PORT" f 2>/dev/null | head -1)

if [[ "$FREQ" =~ ^[0-9]+$ ]]; then
    MHZ=$(awk "BEGIN {printf \"%.6f\", $FREQ / 1000000}")
    log "CAT check successful: FTdx10 reports $MHZ MHz."
else
    log "ERROR: Could not read FTdx10 frequency through rigctld."
    notify "Startup failed: FTdx10 CAT check failed"
    exit 1
fi

# ------------------------------------------------------------
# ardopcf — USB audio + RTS PTT
# ------------------------------------------------------------

if port_open "$ARDOP_PORT"; then
    log "ardopcf is already listening on port $ARDOP_PORT."
else
    log "Starting ardopcf..."

    cd "$ARDOP_DIR" || exit 1

    nohup "$ARDOP_EXE" \
        -p "$PTT_PORT" \
        --hostcommands "MYCALL VE3ZDN;DRIVELEVEL 2" \
        "$ARDOP_PORT" \
        "USB AUDIO  CODEC" \
        "USB AUDIO  CODEC" \
        >"$LOGDIR/ardopcf.log" 2>&1 &

    echo $! > "$LOGDIR/ardopcf.pid"

    if ! wait_for_port "$ARDOP_PORT" "ardopcf"; then
        log "ardopcf did not start correctly."
        tail -40 "$LOGDIR/ardopcf.log"
        notify "Startup failed: ardopcf did not respond"
        exit 1
    fi
fi

# ------------------------------------------------------------
# Pat
# ------------------------------------------------------------

if port_open "$PAT_PORT"; then
    log "Pat is already listening on port $PAT_PORT."
else
    log "Starting Pat..."

    nohup pat http \
        >"$LOGDIR/pat.log" 2>&1 &

    echo $! > "$LOGDIR/pat.pid"

    if ! wait_for_port "$PAT_PORT" "Pat"; then
        tail -30 "$LOGDIR/pat.log"
        notify "Startup failed: Pat did not respond"
        exit 1
    fi
fi

echo
echo "============================================================"
echo "                    STATION READY"
echo "============================================================"
echo
echo " GPS / gpsd   127.0.0.1:$GPSD_PORT     OK"
echo " rigctld      127.0.0.1:$RIGCTLD_PORT     OK"
echo " ardopcf      127.0.0.1:$ARDOP_PORT     OK"
echo " ARDOP Web    127.0.0.1:$ARDOP_WEB_PORT     OK"
echo " Pat          127.0.0.1:$PAT_PORT     OK"
echo
echo " FTdx10 CAT   $CAT_PORT"
echo " FTdx10 PTT   $PTT_PORT (RTS)"
echo " FTdx10 freq  $MHZ MHz"
echo " ARDOP drive  2"
echo
echo " Logs: $LOGDIR"
echo

notify "Station ready — GPS + FTdx10 CAT $MHZ MHz"

open "http://localhost:$ARDOP_WEB_PORT"
open "http://localhost:$PAT_PORT"

exit 0
