param(
    [string]$Port
)

$ErrorActionPreference = 'Stop'
$repo = Join-Path $env:USERPROFILE 'TibiaPilotNG'

# Getarnte USB-Kennung. Ohne sie meldet sich das Board als "Arduino LLC"
# und spielt gleichzeitig Tastatur und Maus - so sieht kein echtes
# Eingabegeraet aus. Siehe arduino/usb-identity.json.
$identitaet = Get-Content (Join-Path $repo 'arduino\usb-identity.json') -Raw | ConvertFrom-Json
$getarnteVid = $identitaet.vid -replace '^0x', ''
$devices = @(Get-CimInstance Win32_PnPEntity | Where-Object {
    $_.Name -match '\(COM\d+\)' -and (
        $_.Name -match 'Arduino|Leonardo|Micro' -or
        $_.PNPDeviceID -match 'VID_(2341|2A03|1B4F|239A)' -or
        $_.PNPDeviceID -match "VID_$getarnteVid"
    )
})
if ($Port) {
    $device = $devices | Where-Object Name -Match "\($([regex]::Escape($Port))\)" |
        Select-Object -First 1
} else {
    $device = $devices | Select-Object -First 1
}
if (!$device) {
    throw 'Kein unterstütztes Arduino-32u4-Board erkannt. USB-Datenkabel prüfen.'
}
if (!$Port) {
    $Port = [regex]::Match($device.Name, '\((COM\d+)\)').Groups[1].Value
}

$fqbn = & (Join-Path $PSScriptRoot 'Resolve-ArduinoFqbn.ps1') `
    -DeviceName $device.Name `
    -PnpDeviceId $device.PNPDeviceID
$cli = & (Join-Path $PSScriptRoot 'Install-ArduinoToolchain.ps1')

$sketch = Join-Path $repo 'arduino\pilotng_leonardo'
# Die getarnte Kennung ueber eine boards.local.txt vorgeben.
#
# Nicht ueber die Kommandozeile: PowerShell 5.1 zerlegt Argumente mit
# Leerzeichen und Anfuehrungszeichen falsch - der Compiler bekam
# -DUSB_PRODUCT=USB Keyboard ohne Zeichenkette und brach ab.
# boards.local.txt ist der vom Arduino-Kern vorgesehene Weg, Board-Werte
# zu ueberschreiben, und kennt dieses Problem nicht.
$boardId = ($fqbn -split ':')[2]
$plattformPfad = Join-Path $env:LOCALAPPDATA "Arduino15\packages\arduino\hardware\avr"
$kernPfad = Get-ChildItem $plattformPfad -Directory -EA SilentlyContinue |
    Sort-Object Name -Descending | Select-Object -First 1
if (!$kernPfad) { throw 'Arduino-AVR-Kern nicht gefunden.' }
$lokal = Join-Path $kernPfad.FullName 'boards.local.txt'
@(
    "# Von TibiaPilotNG erzeugt - siehe arduino/usb-identity.json.",
    "# Ohne diese Werte meldet sich der Chip als Arduino LLC.",
    "$boardId.build.vid=$($identitaet.vid)",
    "$boardId.build.pid=$($identitaet.pid)",
    "$boardId.build.usb_manufacturer=`"$($identitaet.manufacturer)`"",
    "$boardId.build.usb_product=`"$($identitaet.product)`""
) | Set-Content $lokal -Encoding ascii

# Bauen und Uebertragen in EINEM Aufruf: Getrennt legt "compile" die
# Datei woanders ab, und "upload" holt danach eine alte aus dem
# Standardordner - der Chip behielt so seine Arduino-Kennung.
& $cli compile --clean --fqbn $fqbn --upload --port $Port $sketch
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }

# Nach dem Flashen meldet sich ein 32u4 unter einer neuen COM-Nummer
# (z. B. COM3 -> COM5). Also kurz warten und den echten Port merken.
$flashedPort = $Port
for ($attempt = 0; $attempt -lt 20; $attempt++) {
    Start-Sleep -Milliseconds 500
    $current = Get-CimInstance Win32_PnPEntity | Where-Object {
        $_.Name -match '\(COM\d+\)' -and
        ($_.PNPDeviceID -match "VID_$getarnteVid" -or
         $_.PNPDeviceID -match 'VID_(2341|2A03|1B4F|239A)')
    } | Select-Object -First 1
    if ($current) {
        $flashedPort = [regex]::Match($current.Name, '\((COM\d+)\)').Groups[1].Value
        break
    }
}

[Environment]::SetEnvironmentVariable(
    'TIBIAPILOT_ARDUINO_PORT', $flashedPort, 'User'
)
# Modell merken: Nach dem Flashen traegt das Board die getarnte Kennung,
# aus der sich das Modell nicht mehr ablesen laesst.
[Environment]::SetEnvironmentVariable(
    'TIBIAPILOT_ARDUINO_LAST_FQBN', $fqbn, 'User'
)
$Port = $flashedPort

[pscustomobject]@{
    flashed = $true
    board = $device.Name
    fqbn = $fqbn
    port = $Port
} | ConvertTo-Json -Compress
