#!/usr/bin/env bash
set -euo pipefail

# Flash Cricket ESP32-P4 firmware (app only)
# Auto-detects directory structure and works with either:
#   1. Full ESP-IDF project directory (uses idf.py flash)
#   2. Binary files only (uses esptool.py directly)
# Usage: flash_cricket.sh [--force-kill-port] [port]

DEFAULT_PORT="/dev/cu.usbmodem1101"
PORT="$DEFAULT_PORT"
FORCE_KILL_PORT=0

usage() {
  echo "Usage: $(basename "$0") [--force-kill-port] [port]"
  echo "  --force-kill-port   Kill process(es) holding the serial port before flashing"
  exit 1
}

while [[ $# -gt 0 ]]; do
  case "$1" in
    -f|--force-kill-port)
      FORCE_KILL_PORT=1
      shift
      ;;
    -h|--help)
      usage
      ;;
    /dev/*)
      PORT="$1"
      shift
      ;;
    *)
      echo "ERROR: Unknown argument '$1'" >&2
      usage
      ;;
  esac
done

echo "=== Cricket ESP32-P4 Flash ==="

# Auto-detect Cricket directory based on user
if [[ "$USER" == "uhuman" ]]; then
  CRICKET_DIR="/Users/uhuman/PycharmProjects/PlatformIO/Projects/M5Tab5-HalUD/platforms/Cricket_ESP32_P4"
elif [[ "$USER" == "ming" ]]; then
  CRICKET_DIR="/Users/ming/Development/esp32/cricket"
else
  echo "ERROR: Unknown user '$USER' - add your path to this script" >&2
  exit 1
fi
echo "Using: $CRICKET_DIR"

# Source ESP-IDF
if [[ -f "$HOME/export-esp.sh" ]]; then
  source "$HOME/export-esp.sh" > /dev/null 2>&1
elif [[ -f "$HOME/esp/esp-idf/export.sh" ]]; then
  source "$HOME/esp/esp-idf/export.sh" > /dev/null 2>&1
else
  echo "ERROR: ESP-IDF not found" >&2
  echo "  Expected: ~/export-esp.sh or ~/esp/esp-idf/export.sh"
  exit 1
fi

cd "$CRICKET_DIR" || { echo "ERROR: Cannot cd to: $CRICKET_DIR" >&2; exit 1; }

# Auto-detect port if default not found
if [[ ! -e "$PORT" ]]; then
  echo "Port $PORT not found, auto-detecting..."
  DETECTED=$(ls /dev/cu.usbmodem* 2>/dev/null | head -1)
  if [[ -n "$DETECTED" ]]; then
    PORT="$DETECTED"
    echo "Using: $PORT"
  else
    echo "ERROR: No USB modem ports found" >&2
    exit 1
  fi
fi

echo "Project dir: $CRICKET_DIR"
echo "Port: $PORT"

LOCK_PIDS=$(lsof -t "$PORT" 2>/dev/null || true)
if [[ -n "$LOCK_PIDS" ]]; then
  if [[ "$FORCE_KILL_PORT" -eq 1 ]]; then
    echo "Port busy on $PORT. Killing holder PID(s): $LOCK_PIDS"
    for pid in $LOCK_PIDS; do
      kill -9 "$pid" || true
    done
    sleep 1
    LOCK_PIDS_AFTER=$(lsof -t "$PORT" 2>/dev/null || true)
    if [[ -n "$LOCK_PIDS_AFTER" ]]; then
      echo "ERROR: Port still busy after forced kill: $PORT (PID(s): $LOCK_PIDS_AFTER)" >&2
      exit 1
    fi
  else
    echo "ERROR: Port is busy: $PORT" >&2
    lsof "$PORT" >&2 || true
    echo "Hint: re-run with --force-kill-port, or close the process using the port." >&2
    exit 1
  fi
fi

# Check if this is a full ESP-IDF project or just binaries
if [[ -f "CMakeLists.txt" && -f "sdkconfig" ]]; then
  # Full project - use idf.py (handles build if needed)
  echo "Mode: Full ESP-IDF project (using idf.py)"
  echo ""
  idf.py -p "$PORT" flash
else
  # Binary-only - use esptool.py directly
  echo "Mode: Binary files only (using esptool.py)"
  
  # Find binaries - check both build/ subdir and current dir
  if [[ -f "build/cricket.bin" ]]; then
    BUILD_DIR="build"
  elif [[ -f "cricket.bin" ]]; then
    BUILD_DIR="."
  else
    echo "ERROR: cricket.bin not found in $CRICKET_DIR or $CRICKET_DIR/build" >&2
    exit 1
  fi
  
  # Check for required files
  APP_BIN="$BUILD_DIR/cricket.bin"
  BOOTLOADER_BIN="$BUILD_DIR/bootloader/bootloader.bin"
  PARTITION_BIN="$BUILD_DIR/partition_table/partition-table.bin"
  
  # If bootloader/partition not in subdirs, check flat structure
  [[ -f "$BOOTLOADER_BIN" ]] || BOOTLOADER_BIN="$BUILD_DIR/bootloader.bin"
  [[ -f "$PARTITION_BIN" ]] || PARTITION_BIN="$BUILD_DIR/partition-table.bin"
  
  if [[ ! -f "$APP_BIN" ]]; then
    echo "ERROR: App binary not found: $APP_BIN" >&2
    exit 1
  fi
  
  echo "  App: $APP_BIN"
  
  # Flash with esptool.py
  # Addresses from partition table: bootloader@0x2000, partition@0x8000, app@0x10000
  FLASH_ARGS="--chip esp32p4 --port $PORT --baud 921600"
  FLASH_ARGS="$FLASH_ARGS --before default_reset --after hard_reset write_flash"
  FLASH_ARGS="$FLASH_ARGS --flash_mode dio --flash_freq 80m --flash_size 16MB"
  
  # Build flash command based on available files
  FLASH_CMD="esptool.py $FLASH_ARGS"
  
  if [[ -f "$BOOTLOADER_BIN" ]]; then
    echo "  Bootloader: $BOOTLOADER_BIN"
    FLASH_CMD="$FLASH_CMD 0x2000 $BOOTLOADER_BIN"
  fi
  
  if [[ -f "$PARTITION_BIN" ]]; then
    echo "  Partition: $PARTITION_BIN"
    FLASH_CMD="$FLASH_CMD 0x8000 $PARTITION_BIN"
  fi
  
  FLASH_CMD="$FLASH_CMD 0x10000 $APP_BIN"
  
  echo ""
  echo "Flashing..."
  eval $FLASH_CMD
fi

echo ""
echo "✅ Flash complete and successful !"
