# @generated by usage-argv for `mise __complete_word__ --shell powershell`

Register-ArgumentCompleter -Native -CommandName 'mise' -ScriptBlock {
    param($wordToComplete, $commandAst, $cursorPosition)

    $marker = [char]1
    # `$cursorPosition` is an offset into the whole input buffer while `Extent.Text` is only this
    # command's span, so after a pipeline or a `;` the two do not share an origin. Subtracting the
    # extent's start puts them back on the same footing, and cutting here means no offset has to
    # travel — see the bash script on why.
    $extent = $commandAst.Extent
    $offset = $cursorPosition - $extent.StartOffset
    if ($offset -lt 0) { $offset = 0 }
    if ($offset -gt $extent.Text.Length) { $offset = $extent.Text.Length }
    $line = $extent.Text.Substring(0, $offset)
    $out = @(& 'mise' __complete_word__ --shell powershell --line $line 2>$null)

    $files = $null
    $extensions = @()
    $results = [System.Collections.Generic.List[System.Management.Automation.CompletionResult]]::new()
    foreach ($entry in $out) {
        if ([string]::IsNullOrEmpty($entry)) { continue }
        if ($entry -eq ($marker + 'files')) { $files = 'any'; continue }
        if ($entry -eq ($marker + 'dirs')) { $files = 'dirs'; continue }
        if ($entry -eq ($marker + 'executables')) { $files = 'executables'; continue }
        if ($entry -eq ($marker + 'commands')) { $files = 'commands'; continue }
        if ($entry.StartsWith($marker + "extensions`t")) {
            $files = 'extensions'
            $extensions = @($entry -split "`t" | Select-Object -Skip 1 | ForEach-Object { $_.TrimStart('.') })
            continue
        }
        $parts = $entry -split "`t", 4
        $value = $parts[0]
        $description = if ($parts.Count -gt 1 -and $parts[1]) { $parts[1] } else { $value }
        $display = if ($parts.Count -gt 2 -and $parts[2]) { $parts[2] } else { $value }
        $kind = if ($parts.Count -gt 3) {
            switch ($parts[3]) {
                'command' { 'Command' }
                'flag' { 'ParameterName' }
                'file' { 'ProviderItem' }
                'directory' { 'ProviderContainer' }
                default { 'ParameterValue' }
            }
        } else { 'ParameterValue' }
        $results.Add(
            [System.Management.Automation.CompletionResult]::new(
                $value, $display, $kind, $description
            )
        )
    }

    if ($files -eq 'commands') {
        foreach ($command in Get-Command -Name ($wordToComplete + '*') -CommandType Application, ExternalScript -ErrorAction SilentlyContinue) {
            $results.Add(
                [System.Management.Automation.CompletionResult]::new(
                    $command.Name, $command.Name, 'Command', $command.Source
                )
            )
        }
    } elseif ($files) {
        # PowerShell's own, so that `~`, drive-relative paths and provider paths behave as they
        # do everywhere else in the shell.
        foreach ($path in [System.Management.Automation.CompletionCompleters]::CompleteFilename($wordToComplete)) {
            # Trust PowerShell's result type for directories because CompletionText may already
            # carry quoting. Executable leaves are checked as commands after stripping only the
            # outer quote characters PowerShell added.
            if ($files -eq 'dirs' -and $path.ResultType -ne 'ProviderContainer') {
                continue
            }
            if ($files -eq 'executables' -and $path.ResultType -ne 'ProviderContainer') {
                $candidatePath = $path.CompletionText.Trim([char[]]@([char]39, [char]34))
                if (-not (Get-Command -Name $candidatePath -CommandType Application, ExternalScript -ErrorAction SilentlyContinue)) {
                    continue
                }
            }
            if ($files -eq 'extensions' -and $path.ResultType -ne 'ProviderContainer') {
                $candidatePath = $path.CompletionText.Trim([char[]]@([char]39, [char]34))
                $candidateName = [System.IO.Path]::GetFileName($candidatePath)
                $matchesExtension = $false
                foreach ($extension in $extensions) {
                    if ($candidateName.EndsWith('.' + $extension, [System.StringComparison]::OrdinalIgnoreCase)) {
                        $matchesExtension = $true
                        break
                    }
                }
                if (-not $matchesExtension) {
                    continue
                }
            }
            $results.Add($path)
        }
    }

    $results
}
