#!/usr/bin/env bash
#
# flash_pcan.sh — One-click tool to flash canable/candleLight hardware to PCAN-USB compatible firmware
# Supports Ubuntu/macOS. Automatically locates firmware files.
#
# Usage:
#   ./flash_pcan.sh                     # Auto-search firmware
#   ./flash_pcan.sh /path/to/fw.bin     # Specify firmware path manually
#
set -euo pipefail

# ---------- Configuration ----------
FLASH_ADDR="0x08000000"
DFU_VID_PID="0483:df11"      # STM32 ROM DFU bootloader VID:PID
TARGET_VID="0c72"            # PEAK-System VID
FW_NAME_PATTERN="pcan_canable_hw*.bin"

OS="$(uname -s)"


# ---------- Usage Tip ----------
# First execution suggestion:
# bash flash_pcan_mac.sh
# Subsequent execution:
# ./flash_pcan_mac.sh

chmod +x "$0" 2>/dev/null || true


# ---------- Homebrew Dependency Check ----------
if [[ "$OS" == "Darwin" ]]; then
    if ! command -v brew >/dev/null 2>&1; then
        printf '\033[1;31m[✗]\033[0m %s\n' "Homebrew not found, dfu-util cannot be installed automatically"
        echo "Please install Homebrew first"
        echo "Download address: https://brew.sh"
        exit 1
    fi
fi


# ---------- Output Format Functions ----------
info()  { printf '\033[1;34m[INFO]\033[0m %s\n' "$1"; }
ok()    { printf '\033[1;32m[✓]\033[0m %s\n' "$1"; }
warn()  { printf '\033[1;33m[!]\033[0m %s\n' "$1"; }
err()   { printf '\033[1;31m[✗]\033[0m %s\n' "$1"; }

# ---------- 1. Locate Firmware File ----------
find_firmware() {
    # 1) Command line argument priority
    if [[ $# -ge 1 && -n "${1:-}" ]]; then
        if [[ -f "$1" ]]; then
            echo "$1"
            return 0
        else
            err "Path does not exist: $1"
            exit 1
        fi
    fi

    # 2) Auto search directories
    local search_dirs=(
        "$(pwd)"
        "$HOME/Downloads"
        "$HOME/Downloads"
        "$HOME/Desktop"
        "$HOME/Desktop"
        "/mnt/user-data/uploads"
        "/tmp"
    )

    local found=()
    for d in "${search_dirs[@]}"; do
        [[ -d "$d" ]] || continue
        while IFS= read -r -d '' f; do
            found+=("$f")
        done < <(find "$d" -maxdepth 2 -iname "$FW_NAME_PATTERN" -print0 2>/dev/null)
    done

    # Avoid mapfile incompatibility with macOS bash 3.2
    if [[ ${#found[@]} -gt 0 ]]; then
        local uniq=()
        while IFS= read -r line; do
            [[ -n "$line" ]] && uniq+=("$line")
        done < <(printf '%s\n' "${found[@]}" | sort -u)
        found=("${uniq[@]}")
    fi

    if [[ ${#found[@]} -eq 0 ]]; then
        return 1
    elif [[ ${#found[@]} -eq 1 ]]; then
        echo "${found[0]}"
        return 0
    else
        # Multiple firmware candidates, select manually
        warn "Multiple firmware files found, please select:"
        select f in "${found[@]}"; do
            if [[ -n "$f" ]]; then
                echo "$f"
                return 0
            fi
        done
    fi
}

info "Processing: ${FW_NAME_PATTERN}..."
FW_BIN="$(find_firmware "${1:-}" || true)"

if [[ -z "${FW_BIN:-}" ]]; then
    err "Failed to find firmware automatically"
    read -rp "Please input full path of .bin firmware file: " FW_BIN
    if [[ ! -f "$FW_BIN" ]]; then
        err "Path does not exist: $FW_BIN"
        exit 1
    fi
fi

ok "Using firmware: $FW_BIN"
FW_SIZE="$(wc -c < "$FW_BIN" | tr -d ' ')"
info "File size: ${FW_SIZE} bytes"
if command -v sha256sum >/dev/null 2>&1; then
    info "SHA256: $(sha256sum "$FW_BIN" | awk '{print $1}')"
elif command -v shasum >/dev/null 2>&1; then
    info "SHA256: $(shasum -a 256 "$FW_BIN" | awk '{print $1}')"
fi

# ---------- 2. Check / Install dfu-util ----------
if ! command -v dfu-util >/dev/null 2>&1; then
    warn "dfu-util not found..."
    if [[ "$OS" == "Linux" ]]; then
        sudo apt update && sudo apt install -y dfu-util
    elif [[ "$OS" == "Darwin" ]]; then
        if ! command -v brew >/dev/null 2>&1; then
            err "Homebrew not found. Please install Homebrew first: https://brew.sh"
            exit 1
        fi
        brew install dfu-util
    else
        err "Unknown OS: $OS. Please install dfu-util manually"
        exit 1
    fi
fi

if ! command -v dfu-util >/dev/null 2>&1; then
    err "dfu-util not found in PATH. Please check installation"
    exit 1
fi
ok "dfu-util ready ($(dfu-util --version 2>&1 | head -1))"

# ---------- 3. Detect DFU Device ----------
check_dfu_device() {
    if [[ "$OS" == "Linux" ]]; then
        command -v lsusb >/dev/null 2>&1 || { warn "lsusb missing, installing usbutils..."; sudo apt install -y usbutils; }
        lsusb | grep -qi "$DFU_VID_PID"
    elif [[ "$OS" == "Darwin" ]]; then
        # macOS fallback: system_profiler if lsusb/usbutils not installed
        system_profiler SPUSBHostDataType 2>/dev/null | grep -qi "0x0483.*\|df11\|STM Device in DFU Mode\|STMicroelectronics"
    fi
}

info "Checking DFU mode (${DFU_VID_PID})..."
if ! check_dfu_device; then
    err "DFU device not detected"
    echo "   Please follow these steps:"
    echo "   1. Set DIP switch on USB2CAN module to BOOT position"
    echo "   2. Reconnect USB cable"
    if [[ "$OS" == "Darwin" ]]; then
        echo "   3. Run 'system_profiler SPUSBHostDataType' to verify STM32 Bootloader"
    fi
    exit 1
fi
ok "DFU device detected"

# ---------- 4. List alt-setting Information ----------
info "Fetching DFU device information"
sudo dfu-util -l || true
echo ""
read -rp "Confirm alt=0 entry contains name 'Internal Flash', press Enter to start Flash, Ctrl+C to abort..." _

# ---------- 5. Flash Firmware ----------
info "Flashing firmware to ${FLASH_ADDR} ..."
sudo dfu-util -a 0 -s "${FLASH_ADDR}:leave" -D "$FW_BIN"

ok "Flash completed!"
echo ""
echo "Please perform the following steps:"
echo "  1. Unplug USB2CAN device"
echo "  2. Switch DIP switch back to 120R mode"
echo "  3. Wait 3 seconds then re-plug USB"
echo ""
echo "Commands to verify flash result"
if [[ "$OS" == "Linux" ]]; then
    echo "  lsusb | grep ${TARGET_VID}          # PEAK-System device should appear"
    echo "  sudo modprobe peak_usb"
    echo "  ip -br link                          # can0 interface should appear"
else
    echo "  system_profiler SPUSBHostDataType | grep -A3 -i 'peak\|${TARGET_VID}'   # Locate PEAK System PCAN-USB"
fi