#!/usr/bin/env bash
# ESP32 flash helper - Technimal EDGE I/O modules (E02SA / E04SD)
# Flashes a merged.bin downloaded from the web flasher.
#   Usage: ./flash_esp32.sh <PORT> <FILE>
#     Linux:  ./flash_esp32.sh /dev/ttyUSB0 merged.bin
#     macOS:  ./flash_esp32.sh /dev/cu.usbserial-XXXX merged.bin
#
# Works with esptool v4 and v5: v5 renamed the commands and options (write_flash ->
# write-flash, --flash_mode -> --flash-mode, default_reset -> default-reset), and each
# major version warns or errors on the other's spelling. The version is detected below
# and the matching spelling used, so there are no deprecation warnings either way.
set -u

usage() {
    cat <<'EOF'
==================================================
  ESP32 Flash Script Usage Guide
==================================================

Command Syntax:
  ./flash_esp32.sh <PORT> <FILE_PATH>

Examples:
  Linux:  ./flash_esp32.sh /dev/ttyUSB0 merged.bin
  macOS:  ./flash_esp32.sh /dev/cu.usbserial-XXXX merged.bin

Find your port:
  Linux:  ls /dev/ttyUSB* /dev/ttyACM*
  macOS:  ls /dev/cu.*

*Note: quote the path if it contains spaces.
EOF
    exit 1
}

[ $# -ge 2 ] || usage

PORT="$1"
FILE="$2"

if [ ! -f "$FILE" ]; then
    echo "[ERROR] File not found: $FILE"
    echo "Please verify the file path and try again."
    exit 1
fi

# Prefer the esptool launcher; fall back to the Python module.
if command -v esptool >/dev/null 2>&1; then
    ESPTOOL=(esptool)
elif command -v esptool.py >/dev/null 2>&1; then
    ESPTOOL=(esptool.py)
elif command -v python3 >/dev/null 2>&1 && python3 -m esptool version >/dev/null 2>&1; then
    ESPTOOL=(python3 -m esptool)
else
    echo "[ERROR] esptool not found. Install it with:  pip install esptool"
    exit 1
fi

# Pick the option spelling for the esptool actually installed (see note at the top).
ESPVER=$("${ESPTOOL[@]}" version 2>/dev/null | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1)
if [ "${ESPVER%%.*}" = "4" ]; then
    WRITE=write_flash; BEFORE=default_reset; AFTER=hard_reset
    F_MODE=--flash_mode; F_FREQ=--flash_freq; F_SIZE=--flash_size
else
    WRITE=write-flash; BEFORE=default-reset; AFTER=hard-reset
    F_MODE=--flash-mode; F_FREQ=--flash-freq; F_SIZE=--flash-size
fi

echo "--------------------------------------------------"
echo "[INFO] Starting ESP32 Flashing Process..."
echo "[INFO] TARGET PORT: $PORT"
echo "[INFO] TARGET FILE: $FILE"
echo "[INFO] ESPTOOL:     ${ESPTOOL[*]} (v${ESPVER:-unknown})"
echo "--------------------------------------------------"

"${ESPTOOL[@]}" --chip esp32 --port "$PORT" --baud 460800 \
    --before "$BEFORE" --after "$AFTER" \
    "$WRITE" "$F_MODE" dio "$F_FREQ" 40m "$F_SIZE" detect \
    0x0 "$FILE"
RC=$?

if [ "$RC" -eq 0 ]; then
    echo "--------------------------------------------------"
    echo "[SUCCESS] ESP32 has been flashed successfully!"
    echo "--------------------------------------------------"
else
    echo "--------------------------------------------------"
    echo "[ERROR] An error occurred during the flashing process."
    echo "  - Close any serial monitor still holding $PORT"
    echo "  - Linux: add yourself to the 'dialout' group"
    echo "           (sudo usermod -aG dialout \$USER, then re-login) or use sudo"
    echo "  - If it cannot connect, hold BOOT (GPIO0) while starting"
    echo "--------------------------------------------------"
fi

exit "$RC"
