param(
    [Parameter(Mandatory=$true)]
    [long]$SymEditorHwnd,
    [Parameter(Mandatory=$true)]
    [long]$SearchEditHwnd,
    [Parameter(Mandatory=$true)]
    [string]$SymbolName
)

# ============================================================================
# BACKGROUND-ONLY symbol navigation.
#
# The previous version did ALL of this just to type one symbol name:
#   * an Alt-key trick to steal foreground permission,
#   * ShowWindow(SW_RESTORE) + SetForegroundWindow  -> took over the screen,
#   * SetCursorPos + mouse_event                    -> MOVED THE USER'S MOUSE,
#   * SendKeys::SendWait                            -> typed into whatever had focus.
# If the user was working, we typed on top of them.
# (John, 2026-07-20: "when you take over my screen to type into the kicad window
# it's crazy rude" — he was running five other projects at the time.)
#
# Everything below is WINDOW-targeted instead of FOCUS-targeted, so it works
# while KiCad sits behind other apps and the user keeps typing elsewhere:
#   1. UIA ValuePattern.SetValue()  — set the search box text with no focus.
#   2. WM_SETTEXT via SendMessage   — fallback for controls without ValuePattern.
#   3. PostMessage(WM_KEYDOWN/UP)   — keys delivered to a specific hwnd, never to
#                                     the shared foreground input queue.
# No keybd_event, no SendKeys, no mouse, no SetForegroundWindow. Ever.
# ============================================================================

Add-Type -AssemblyName UIAutomationClient
Add-Type -AssemblyName UIAutomationTypes

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

public class Win32Nav {
    [DllImport("user32.dll", CharSet = CharSet.Unicode)]
    public static extern IntPtr SendMessageW(IntPtr hWnd, uint Msg, IntPtr wParam, string lParam);
    [DllImport("user32.dll")]
    public static extern bool PostMessageW(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
    [DllImport("user32.dll")]
    public static extern int GetWindowTextLengthW(IntPtr hWnd);
    [DllImport("user32.dll", CharSet = CharSet.Unicode)]
    public static extern int GetWindowTextW(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
    [DllImport("user32.dll")]
    public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
}
"@

$WM_SETTEXT = 0x000C
$WM_KEYDOWN = 0x0100
$WM_KEYUP   = 0x0101
$VK_RETURN  = 0x0D

$hwnd     = [IntPtr]$SymEditorHwnd
$editHwnd = [IntPtr]$SearchEditHwnd
$method   = "none"

# SW_SHOWNOACTIVATE (4): un-minimise so the window can be screenshotted, but do
# NOT activate it. This is the strongest thing the bridge is allowed to do.
[Win32Nav]::ShowWindow($hwnd, 4) | Out-Null

# --- 1. UIA ValuePattern: set the text on the control itself, no focus -------
try {
    $el = [System.Windows.Automation.AutomationElement]::FromHandle($editHwnd)
    if ($el -ne $null) {
        $vp = $null
        if ($el.TryGetCurrentPattern([System.Windows.Automation.ValuePattern]::Pattern, [ref]$vp)) {
            $vp.SetValue($SymbolName)
            $method = "uia-valuepattern"
        }
    }
} catch { }

# --- 2. Fallback: WM_SETTEXT straight to the edit control -------------------
if ($method -eq "none") {
    try {
        [Win32Nav]::SendMessageW($editHwnd, $WM_SETTEXT, [IntPtr]::Zero, $SymbolName) | Out-Null
        $method = "wm_settext"
    } catch { }
}

if ($method -eq "none") {
    Write-Output "ERROR:Could not set search text without focus (no ValuePattern, WM_SETTEXT failed)"
    exit 1
}

Start-Sleep -Milliseconds 250

# --- 3. Commit the filter: Enter POSTED to the edit control ------------------
# PostMessage targets that control's own message queue, so it needs no focus and
# cannot land in another app if the user switches windows mid-call.
[Win32Nav]::PostMessageW($editHwnd, $WM_KEYDOWN, [IntPtr]$VK_RETURN, [IntPtr]::Zero) | Out-Null
[Win32Nav]::PostMessageW($editHwnd, $WM_KEYUP,   [IntPtr]$VK_RETURN, [IntPtr]::Zero) | Out-Null
Start-Sleep -Milliseconds 900

# NOTE: loading the highlighted symbol into the canvas (the old Ctrl+Shift+E) is
# deliberately NOT done here. A ctrl chord can't be delivered reliably by
# PostMessage without focus, and the caller has a better fully-background route:
# the embedded-plugin WM_COMMAND pathway. This script only does the focus-free part.

$len = [Win32Nav]::GetWindowTextLengthW($hwnd)
if ($len -gt 0) {
    $sb = New-Object System.Text.StringBuilder($len + 1)
    [Win32Nav]::GetWindowTextW($hwnd, $sb, $len + 1) | Out-Null
    $title = $sb.ToString()
    if ($title -match [regex]::Escape($SymbolName)) {
        Write-Output "OK:$title|method=$method"
    } elseif ($title -notmatch "no symbol loaded") {
        Write-Output "PARTIAL:$title|method=$method"
    } else {
        Write-Output "NOLOAD:$title|method=$method"
    }
} else {
    Write-Output "PARTIAL:|method=$method"
}