# Launch a specific editor from the KiCad project manager using UI Automation.
# Usage: launch_editor.ps1 -EditorName "Footprint Editor"
# Also supports: "Symbol Editor", "PCB Editor", "Schematic Editor", "Gerber Viewer", etc.
param(
    [Parameter(Mandatory=$true)]
    [string]$EditorName,
    [Parameter(Mandatory=$false)]
    [long]$KiCadHwnd = 0
)

Add-Type -AssemblyName UIAutomationClient
Add-Type -AssemblyName UIAutomationTypes
Add-Type -AssemblyName System.Windows.Forms

Add-Type @"
using System;
using System.Runtime.InteropServices;

public class Win32Launch {
    [DllImport("user32.dll")]
    public static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, UIntPtr dwExtraInfo);
    [DllImport("user32.dll")]
    public static extern bool SetForegroundWindow(IntPtr hWnd);
    [DllImport("user32.dll")]
    public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
    [DllImport("user32.dll")]
    public static extern IntPtr GetForegroundWindow();
}
"@

# If no HWND provided, find KiCad window
if ($KiCadHwnd -eq 0) {
    $procs = Get-Process -Name "kicad" -ErrorAction SilentlyContinue
    if ($procs) {
        $KiCadHwnd = $procs[0].MainWindowHandle.ToInt64()
    }
    if ($KiCadHwnd -eq 0) {
        Write-Output "ERROR:KiCad not found"
        exit 1
    }
}

$hwnd = [IntPtr]$KiCadHwnd

# BACKGROUND ONLY (John, 2026-07-20). UIA InvokePattern drives a control through
# the accessibility tree, which needs NO focus — so we never take the user's
# screen. SW_SHOWNOACTIVATE (4) just un-minimises so the window is screenshottable.
[Win32Launch]::ShowWindow($hwnd, 4) | Out-Null
Start-Sleep -Milliseconds 200

# Use UI Automation to find the launcher text
$root = [System.Windows.Automation.AutomationElement]::FromHandle($hwnd)
if (-not $root) {
    Write-Output "ERROR:Cannot get UI Automation element for KiCad"
    exit 1
}

# Search for a Text element matching the editor name
$condition = New-Object System.Windows.Automation.PropertyCondition(
    [System.Windows.Automation.AutomationElement]::NameProperty,
    $EditorName
)

$element = $root.FindFirst(
    [System.Windows.Automation.TreeScope]::Descendants,
    $condition
)

if (-not $element) {
    Write-Output "ERROR:Could not find '$EditorName' in KiCad UI"
    exit 1
}

# Try to get an InvokePattern (clickable element)
try {
    $invokePattern = $element.GetCurrentPattern([System.Windows.Automation.InvokePattern]::Pattern)
    $invokePattern.Invoke()
    Write-Output "OK:Invoked $EditorName via InvokePattern"
    exit 0
} catch {
    # No InvokePattern — this is a text label, not a button.
    # Fall back to clicking at the element's location.
}

# Get the element's bounding rectangle and click on it
$rect = $element.Current.BoundingRectangle
if ($rect.IsEmpty) {
    Write-Output "ERROR:Element has no bounding rectangle"
    exit 1
}

$clickX = [int]($rect.X + $rect.Width / 2)
$clickY = [int]($rect.Y + $rect.Height / 2)

# Use SendKeys mouse simulation: move cursor and click
[System.Windows.Forms.Cursor]::Position = New-Object System.Drawing.Point($clickX, $clickY)
Start-Sleep -Milliseconds 100

# Simulate click
Add-Type @"
using System;
using System.Runtime.InteropServices;

public class MouseClick {
    [DllImport("user32.dll")]
    public static extern void mouse_event(uint dwFlags, int dx, int dy, uint dwData, UIntPtr dwExtraInfo);
}
"@

[MouseClick]::mouse_event(0x0002, 0, 0, 0, [UIntPtr]::Zero)  # LEFTDOWN
Start-Sleep -Milliseconds 30
[MouseClick]::mouse_event(0x0004, 0, 0, 0, [UIntPtr]::Zero)  # LEFTUP

Write-Output "OK:Clicked at ($clickX, $clickY) on $EditorName"