#!/bin/bash
# -- MOTHERBOARD TABLE ---------------------------------------------------------
register_board() {
    local name="$1" path="$2" flag="${3:-}"
    _BOARD_PATHS["$name"]="$path"
    _BOARD_FLAGS["$name"]="$flag"
}
declare -A _BOARD_PATHS _BOARD_FLAGS

#         BOARD NAME      SCRIPT PATH                           FLAG
register_board "H12SSW-AN6"  "h12ssw-an6/h12ssw-an6_bios.sh"    "OOB"
register_board "X10DDW-i"    "x10ddw-i/x10ddw-i_bios.sh"
register_board "X10DRH-CT"   "x10drh-ct/x10drh-ct_bios.sh"
register_board "X10DRi"      "x10dri/x10dri_bios.sh"
register_board "X10DRi-T"    "x10dri/x10dri_bios.sh"
register_board "X10SLM-F"    "x10slm-f/x10slm-f_bios.sh"
register_board "X10SRi-F"    "x10sri-f/x10sri-f_bios.sh"
register_board "X11DDW-NT"   "x11ddw-nt/x11ddw-nt_bios.sh"
register_board "X11DPH-T"    "x11dph-t/x11dph-t_bios.sh"
register_board "X11DPU"      "x11dpu/x11dpu_bios.sh"
register_board "X11SCH-F"    "x11sch-f/x11sch-f_bios.sh"
register_board "X11SSH-F"    "x11ssh-f/x11ssh-f_bios.sh"
register_board "X11SSL-CF"   "x11ssl-cf/x11ssl-cf_bios.sh"
register_board "X12DDW-A6"   "x12ddw-a6/x12ddw-a6_bios.sh"      "OOB"
register_board "X12STH-SYS"  "x12sth-sys/x12sth-sys_bios.sh"    "OOB"
register_board "X12STW-TF"   "x12stw-tf/x12stw-tf_bios.sh"      "OOB"
register_board "X13DDW-A"    "x13ddw-a/x13ddw-a_bios.sh"        "OOB"
# -----------------------------------------------------------------------------

export TERM=xterm
BASE_URL="216.104.40.250/tools/bios"
LOG=/root/bios_update.log
# Use unique session name per run so we don't conflict with previous sessions
TMUX_SESSION="bios_update_$$"
OOB_WARN="WARNING: IF UPDATE FAILS DUE TO OOB ACTIVATION YOU WILL NEED TO DO THE UPDATE MANUALLY VIA USB OR IPMI WEBUI!"

# Timeout: 45 minutes (BIOS flash + ME firmware can take a while)
TIMEOUT=2700

rm -rf /root/sum_2.9.0_Linux_x86_64* 2>/dev/null
rm -rf /tmp/sum_2.9.0_Linux_x86_64* 2>/dev/null

MOTHERBOARD=$(dmidecode -t 2 | grep 'Product Name' | awk '{print $3}')

ENTRY_PATH="${_BOARD_PATHS[$MOTHERBOARD]}"
FLAG="${_BOARD_FLAGS[$MOTHERBOARD]}"

if [ -z "$ENTRY_PATH" ]; then
    echo "$MOTHERBOARD NOT SUPPORTED BY SCRIPT -- NO UPDATES APPLIED!"
    echo "EXITING SCRIPT!"
    rm -f "$0"
    exit 0
fi

SCRIPT=$(basename "$ENTRY_PATH")
URL="${BASE_URL}/${ENTRY_PATH}"

echo "$MOTHERBOARD DETECTED -- PROCEEDING WITH BIOS UPDATE!"
[ "$FLAG" = "OOB" ] && echo "$OOB_WARN"

wget -q "$URL" && chmod +x "$SCRIPT"

# Don't kill any tmux sessions - they may be running other operations
rm -f "$LOG"

tmux new-session -d -s "$TMUX_SESSION" -x 220 -y 50 \
    "bash $SCRIPT; echo __BIOS_UPDATE_DONE__ >> $LOG"
tmux pipe-pane -t "$TMUX_SESSION" "stdbuf -o0 cat >> $LOG"

echo "Tmux session '$TMUX_SESSION' started -- streaming output..."
echo "--------------------------------------------------------"

ELAPSED=0
SEEN_DONE=false
ALREADY_LATEST=false
LAST_BYTES=0
LAST_SUM_PCT=""
LAST_SUM_PHASE=""
LAST_OUTPUT_TIME=0

clean_line() {
    local line="$1"
    [ -z "$line" ] && return 1
    echo "$line" | grep -qE "\[=*>?[[:space:]]*\]" && return 1
    echo "$line" | grep -qE "[0-9]+(\.[0-9]+)? [KMG]B/s[[:space:]]*$" && return 1
    echo "$line" | grep -qE "^[[:space:]]*[0-9]+%\[" && return 1
    echo "$line" | grep -qE "^[[:space:]]{10,}$" && return 1
    echo "$line" | grep -qE "saved \[.*\]" && return 1
    echo "$line" | grep -qE "^(Connecting to |HTTP request sent|Length:|Saving to:)" && return 1
    echo "$line" | grep -qE "^[[:space:]]*[/|\\-][[:space:]]*$" && return 1
    return 0
}

filter_sum_progress() {
    local line="$1"
    if echo "$line" | grep -qE "(Reading|Writing|Verifying|Erasing|Putting|Comparing) .* \([0-9]+%\)"; then
        local pct phase
        pct=$(echo "$line" | grep -oE '\([0-9]+%\)' | tr -d '()%')
        phase=$(echo "$line" | grep -oE '^[A-Za-z]+')
        if [ "$phase" != "$LAST_SUM_PHASE" ] || \
           [ "$pct" = "0" ] || [ "$pct" = "100" ] || \
           [ $(( pct % 10 )) -eq 0 -a "$pct" != "$LAST_SUM_PCT" ]; then
            LAST_SUM_PCT="$pct"
            LAST_SUM_PHASE="$phase"
            echo "[PROGRESS] $line"
        fi
        return 0
    fi
    echo "$line"
    return 0
}

process_new_bytes() {
    local current_bytes=$1
    if [ "$current_bytes" -le "$LAST_BYTES" ]; then
        return
    fi
    # Use tail -c instead of dd bs=1 (much faster)
    local new_content
    new_content=$(tail -c +"$(( LAST_BYTES + 1 ))" "$LOG" 2>/dev/null | head -c $(( current_bytes - LAST_BYTES )))
    LAST_BYTES=$current_bytes
    
    while IFS= read -r seg; do
        [ -z "$seg" ] && continue
        echo "$seg" | grep -q "__BIOS_UPDATE_DONE__" && { SEEN_DONE=true; continue; }
        clean_line "$seg" || continue
        filter_sum_progress "$seg"
        if echo "$seg" | grep -qiE "^UPDATE COMPLETE"; then
            SEEN_DONE=true
        fi
        if echo "$seg" | grep -qiE "latest version|already.*latest|no update"; then
            ALREADY_LATEST=true
        fi
        LAST_OUTPUT_TIME=$ELAPSED
    done < <(printf '%s' "$new_content" | tr '\r' '\n')
}

while [ $ELAPSED -lt $TIMEOUT ]; do
    if grep -q "__BIOS_UPDATE_DONE__" "$LOG" 2>/dev/null; then
        SEEN_DONE=true
        CURRENT_BYTES=$(wc -c < "$LOG" 2>/dev/null || echo 0)
        process_new_bytes "$CURRENT_BYTES"
        break
    fi

    CURRENT_BYTES=$(wc -c < "$LOG" 2>/dev/null || echo 0)
    process_new_bytes "$CURRENT_BYTES"
    
    # Heartbeat every 30 seconds of idle time to keep SSH alive
    IDLE=$(( ELAPSED - LAST_OUTPUT_TIME ))
    if [ $IDLE -gt 0 ] && [ $(( IDLE % 30 )) -eq 0 ]; then
        echo "[Working... ${IDLE}s idle, ${ELAPSED}s total]"
    fi

    sleep 1
    ELAPSED=$(( ELAPSED + 1 ))
done

if [ "$SEEN_DONE" = true ] && [ "$ALREADY_LATEST" = false ]; then
    echo "============================================================"
    echo "  BIOS flash script finished inside tmux session."
    echo "  A reboot is required to apply the new BIOS."
    echo "  Tmux session '$TMUX_SESSION' has been LEFT RUNNING."
    echo "============================================================"
    echo "BIOS UPDATE SUCCESSFUL"
elif [ "$SEEN_DONE" = true ] && [ "$ALREADY_LATEST" = true ]; then
    echo "BIOS already at latest version - no update needed"
    echo "Tmux session '$TMUX_SESSION' has been LEFT RUNNING."
elif [ "$SEEN_DONE" != true ]; then
    echo "WARNING: Timed out after ${TIMEOUT}s waiting for tmux session to complete."
    echo "Check tmux session '$TMUX_SESSION' on the remote host manually."
    echo "  tmux attach -t $TMUX_SESSION"
    echo "  tail -f $LOG"
fi

# Never kill tmux sessions - they may still be doing important work
rm -f "$0"
exit 0