#!/bin/bash
# -- MOTHERBOARD TABLE ---------------------------------------------------------
register_board() {
    local name="$1" path="$2"
    _BOARD_PATHS["$name"]="$path"
}
declare -A _BOARD_PATHS
register_board "H12SSW-AN6"  "h12ssw-an6/h12ssw-an6_ipmi.sh"
register_board "X10DDW-i"    "x10ddw-i/x10ddw-i_ipmi.sh"
register_board "X10DRH-CT"   "x10drh-ct/x10drh-ct_ipmi.sh"
register_board "X10DRi"      "x10dri/x10dri_ipmi.sh"
register_board "X10DRi-T"    "x10dri/x10dri_ipmi.sh"
register_board "X10SLM-F"    "x10slm-f/x10slm-f_ipmi.sh"
register_board "X10SRi-F"    "x10sri-f/x10sri-f_ipmi.sh"
register_board "X11DDW-NT"   "x11ddw-nt/x11ddw-nt_ipmi.sh"
register_board "X11DPH-T"    "x11dph-t/x11dph-t_ipmi.sh"
register_board "X11DPU"      "x11dpu/x11dpu_ipmi.sh"
register_board "X11SCH-F"    "x11sch-f/x11sch-f_ipmi.sh"
register_board "X11SSH-F"    "x11ssh-f/x11ssh-f_ipmi.sh"
register_board "X11SSL-CF"   "x11ssl-cf/x11ssl-cf_ipmi.sh"
register_board "X12DDW-A6"   "x12ddw-a6/x12ddw-a6_ipmi.sh"
register_board "X12STH-SYS"  "x12sth-sys/x12sth-sys_ipmi.sh"
register_board "X12STW-TF"   "x12stw-tf/x12stw-tf_ipmi.sh"
register_board "X13DDW-A"    "x13ddw-a/x13ddw-a_ipmi.sh"
# =============================================================================

export TERM=xterm
BASE_URL="216.104.40.250/tools/ipmi"
LOG=/root/ipmi_update.log
# Use unique session name per run so we don't conflict with previous sessions
TMUX_SESSION="ipmi_update_$$"

# Timeout: 60 minutes
TIMEOUT=3600

rm -rf /root/ipmi_updater.sh
rm -rf /tmp/ipmi_updater.sh
rm -rf /tmp/sum_2.9.0_Linux_x86_64*
rm -rf /root/sum_2.9.0_Linux_x86_64*

MOTHERBOARD=$(dmidecode -t 2 | grep 'Product Name' | cut -d ' ' -f 3)
ENTRY_PATH="${_BOARD_PATHS[$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 IPMI UPDATE!"

SCRIPT_PATH="/root/$SCRIPT"
if ! wget -q "$URL" -O "$SCRIPT_PATH"; then
    echo "ERROR: Failed to download board script"
    echo "EXITING SCRIPT!"
    rm -f "$0"
    exit 1
fi
chmod +x "$SCRIPT_PATH"

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

echo "Starting IPMI flash in tmux session '$TMUX_SESSION'..."

# Run board script inside tmux, then signal completion via done marker
# Using pipe-pane preserves visible output in the tmux session
tmux new-session -d -s "$TMUX_SESSION" -x 220 -y 50 \
    "bash $SCRIPT_PATH < /dev/null; echo __IPMI_DONE__ >> $LOG"
tmux pipe-pane -t "$TMUX_SESSION" "stdbuf -o0 cat >> $LOG"

echo "Tmux session started -- streaming output..."
echo "--------------------------------------------------------"

ELAPSED=0
SEEN_DONE=false
LAST_BYTES=0
LAST_SUM_PCT=""
LAST_SUM_PHASE=""
LAST_UPLOAD_PART=""
LAST_UPLOAD_PCT=""
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_progress() {
    local line="$1"
    
    # "Upload part N XXXXX bytes, NN%" -- buffer silently, emit one line when part changes or hits 100%
    if echo "$line" | grep -qE "Upload part [0-9]+[[:space:]]+[0-9]+ bytes,[[:space:]]+[0-9]+%"; then
        local part pct
        part=$(echo "$line" | grep -oE "Upload part [0-9]+" | grep -oE "[0-9]+$")
        pct=$(echo "$line" | grep -oE "[0-9]+%" | tail -1 | tr -d '%')
        # New part starting -- announce it
        if [ "$part" != "$LAST_UPLOAD_PART" ]; then
            LAST_UPLOAD_PART="$part"
            LAST_UPLOAD_PCT="0"
            echo "Upload part $part: uploading..."
        fi
        # Update in-progress percentage every 10% via a ticker line prefixed [PROGRESS]
        # so the frontend can overwrite instead of append
        if [ $(( pct % 10 )) -eq 0 ] && [ "$pct" != "$LAST_UPLOAD_PCT" ]; then
            LAST_UPLOAD_PCT="$pct"
            echo "[PROGRESS] Upload part $part: ${pct}%"
        fi
        return 0
    fi
    
    # Upload complete
    if echo "$line" | grep -qE "Upload part [0-9]+.*\[Ok\]"; then
        local part
        part=$(echo "$line" | grep -oE "Upload part [0-9]+" | grep -oE "[0-9]+$")
        echo "Upload part $part: 100% -- COMPLETE [Ok]"
        LAST_UPLOAD_PCT="100"
        return 0
    fi
    
    # Filter SUM Reading/Writing/Verifying/Erasing progress - only show every 10%
    if echo "$line" | grep -qE "(Reading|Writing|Verifying|Erasing|Putting) .* \([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 ] && [ "$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
    local new_content
    new_content=$(tail -c +"$(( LAST_BYTES + 1 ))" "$LOG" 2>/dev/null | head -c $(( current_bytes - LAST_BYTES )))
    LAST_BYTES=$current_bytes
    
    # Convert \r to \n so each progress update becomes its own line for processing
    while IFS= read -r seg; do
        [ -z "$seg" ] && continue
        echo "$seg" | grep -q "__IPMI_DONE__" && { SEEN_DONE=true; continue; }
        clean_line "$seg" || continue
        filter_progress "$seg"
        LAST_OUTPUT_TIME=$ELAPSED
    done < <(printf '%s' "$new_content" | tr '\r' '\n')
}

while [ $ELAPSED -lt $TIMEOUT ]; do
    if grep -q "__IPMI_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 ]; then
    echo "============================================================"
    echo "  IPMI flash script finished inside tmux session."
    echo "  BMC will reset to apply firmware. This is normal."
    echo "  Tmux session '$TMUX_SESSION' has been LEFT RUNNING."
    echo "============================================================"
    echo "IPMI UPDATE SUCCESSFUL"
else
    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