# =============================================================================
# ADA P1 Meter - Native Firmware Updater (English Version)
# =============================================================================

$ErrorActionPreference = "Continue"

Write-Host "==============================================" -ForegroundColor Cyan
Write-Host "    ADA P1 Meter - Firmware Updater           " -ForegroundColor Cyan
Write-Host "==============================================`n" -ForegroundColor Cyan

# 1. Port Detection (Combined bulletproof method)
Write-Host "[*] Searching for devices..." -ForegroundColor Gray

# Attempt to get descriptive names via PnP
$pnpPorts = Get-WmiObject Win32_PnPEntity | Where-Object { $_.Name -match '\(COM\d+\)' }

# Get raw port names from the system
$rawPortNames = [System.IO.Ports.SerialPort]::GetPortNames() | Sort-Object -Unique

$ports = @()

if ($rawPortNames.Count -gt 0) {
    foreach ($rawName in $rawPortNames) {
        $matchingPnp = $pnpPorts | Where-Object { $_.Name -contains "($rawName)" -or $_.Name -match "\($rawName\)" }
        
        if ($matchingPnp) {
            $ports += [PSCustomObject]@{ Name = $matchingPnp.Name; DeviceID = $rawName }
        } else {
            # Fallback to raw name if descriptive name is unavailable
            $ports += [PSCustomObject]@{ Name = "Serial Device ($rawName)"; DeviceID = $rawName }
        }
    }
}

if ($ports.Count -eq 0) {
    Write-Host "[-] No active COM ports found! Please plug in the ADA P1." -ForegroundColor Red
    Read-Host "Press Enter to exit..."
    exit
}

Write-Host "[+] Available ports:" -ForegroundColor Yellow
$portMap = @{}
for ($i = 0; $i -lt $ports.Count; $i++) {
    $p = $ports[$i]
    $portMap[$i + 1] = $p.DeviceID
    Write-Host "  $($i + 1). $($p.Name)"
}

# 2. Port Selection
$selection = Read-Host "`nSelect the port number (1-$($ports.Count))"
if ($selection -match '^\d+$' -and $portMap.ContainsKey([int]$selection)) {
    $targetPort = $portMap[[int]$selection]
} else {
    Write-Host "[-] Invalid selection!" -ForegroundColor Red
    Read-Host "Press Enter to exit..."
    exit
}

# 3. Path Setup (Firmware v1.7.2)
$PSScriptRoot = Split-Path -Parent $MyInvocation.MyCommand.Definition
$toolExe     = Join-Path $PSScriptRoot "tools\esptool.exe"
$binBoot     = Join-Path $PSScriptRoot "ada\ada_1_7_2.ino.bootloader.bin"
$binParts    = Join-Path $PSScriptRoot "ada\ada_1_7_2.ino.partitions.bin"
$binBootApp  = Join-Path $PSScriptRoot "ada\boot_app0.bin"
$binFirmware = Join-Path $PSScriptRoot "ada\ada_1_7_2.ino.bin"

if (-not (Test-Path $toolExe)) {
    Write-Host "[-] ERROR: $toolExe not found!" -ForegroundColor Red
    Read-Host "Press Enter to exit..."
    exit
}

# 4. Flashing
Write-Host "`n>>> Starting firmware upload on $targetPort..." -ForegroundColor Green
& "$toolExe" --chip esp32 --port "$targetPort" --baud 921600 --before default_reset --after hard_reset write_flash -z --flash_mode keep --flash_freq keep --flash_size keep 0x1000 "$binBoot" 0x8000 "$binParts" 0xe000 "$binBootApp" 0x10000 "$binFirmware"

if ($LASTEXITCODE -ne 0) {
    Write-Host "`n[-] ERROR occurred during upload!" -ForegroundColor Red
    Read-Host "Press Enter to exit..."
    exit
}

# 5. Monitoring
Write-Host "`n>>> Starting monitor (max 120s) for successful boot..." -ForegroundColor Yellow
try {
    $portObj = New-Object System.IO.Ports.SerialPort $targetPort, 115200, None, 8, One
    $portObj.Open()
    $startTime = Get-Date
    $buffer = ""

    while ($portObj.IsOpen -and ((Get-Date) - $startTime).TotalSeconds -lt 120) {
        if ($portObj.BytesToRead -gt 0) {
            $data = $portObj.ReadExisting()
            $buffer += $data
            Write-Host $data -NoNewline
            
            if ($buffer -match "HTTP server started\." -or $buffer -match "WiFi connected") {
                Write-Host "`n`n[OK] ADA has started successfully and connected!" -ForegroundColor Green
                break
            }
        }
        Start-Sleep -Milliseconds 100
    }
    $portObj.Close()
} catch {
    Write-Host "`n[!] Monitor error: $_" -ForegroundColor DarkYellow
}

Write-Host "`n=== FINISHED ===" -ForegroundColor Cyan
Read-Host "Press Enter to close..."