
using namespace System.Management.Automation
using namespace System.Management.Automation.Language

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

    $commandElements = $commandAst.CommandElements
    $command = @(
        'ordinaryd'
        for ($i = 1; $i -lt $commandElements.Count; $i++) {
            $element = $commandElements[$i]
            if ($element -isnot [StringConstantExpressionAst] -or
                $element.StringConstantType -ne [StringConstantType]::BareWord -or
                $element.Value.StartsWith('-') -or
                $element.Value -eq $wordToComplete) {
                break
        }
        $element.Value
    }) -join ';'

    $completions = @(switch ($command) {
        'ordinaryd' {
            [CompletionResult]::new('--data-dir', '--data-dir', [CompletionResultType]::ParameterName, 'specify the data directory')
            [CompletionResult]::new('--log-level', '--log-level', [CompletionResultType]::ParameterName, 'base log level for every component')
            [CompletionResult]::new('--log-file-rotation', '--log-file-rotation', [CompletionResultType]::ParameterName, 'rate at which new log files are generated')
            [CompletionResult]::new('--stdio-logs', '--stdio-logs', [CompletionResultType]::ParameterName, 'logs events to stdio')
            [CompletionResult]::new('--stdio-pretty', '--stdio-pretty', [CompletionResultType]::ParameterName, 'whether to pretty print stdio logs')
            [CompletionResult]::new('--stdio-json', '--stdio-json', [CompletionResultType]::ParameterName, 'whether to print stdio logs as json')
            [CompletionResult]::new('--json-logs', '--json-logs', [CompletionResultType]::ParameterName, 'persists JSON formatted log lines to <data-dir>/logs/')
            [CompletionResult]::new('--with-span-timing', '--with-span-timing', [CompletionResultType]::ParameterName, 'dictates whether timing information should be logged')
            [CompletionResult]::new('--log-size', '--log-size', [CompletionResultType]::ParameterName, 'whether storage sizes are logged')
            [CompletionResult]::new('-h', '-h', [CompletionResultType]::ParameterName, 'Print help')
            [CompletionResult]::new('--help', '--help', [CompletionResultType]::ParameterName, 'Print help')
            [CompletionResult]::new('-V', '-V ', [CompletionResultType]::ParameterName, 'Print version')
            [CompletionResult]::new('--version', '--version', [CompletionResultType]::ParameterName, 'Print version')
            [CompletionResult]::new('init', 'init', [CompletionResultType]::ParameterValue, 'initialize the environment for an Ordinary API server')
            [CompletionResult]::new('api', 'api', [CompletionResultType]::ParameterValue, 'start the Ordinary API server')
            [CompletionResult]::new('app', 'app', [CompletionResultType]::ParameterValue, 'start an Ordinary Application server')
            [CompletionResult]::new('help', 'help', [CompletionResultType]::ParameterValue, 'Print this message or the help of the given subcommand(s)')
            break
        }
        'ordinaryd;init' {
            [CompletionResult]::new('--environment', '--environment', [CompletionResultType]::ParameterName, 'environment (e.g production, development, staging)')
            [CompletionResult]::new('--storage-size', '--storage-size', [CompletionResultType]::ParameterName, 'Storage size in bytes (rounded up to nearest OS page size)')
            [CompletionResult]::new('--api-domain', '--api-domain', [CompletionResultType]::ParameterName, 'domain name for API console')
            [CompletionResult]::new('--password', '--password', [CompletionResultType]::ParameterName, 'instance user password')
            [CompletionResult]::new('--api-contacts', '--api-contacts', [CompletionResultType]::ParameterName, 'contacts for the API domain cert provisioning')
            [CompletionResult]::new('--app-domains', '--app-domains', [CompletionResultType]::ParameterName, 'domains that apps can subdomain off of')
            [CompletionResult]::new('--privileged-domains', '--privileged-domains', [CompletionResultType]::ParameterName, 'list of applications that have access to API server level commands (i.e. API server invite token generation)')
            [CompletionResult]::new('--data-dir', '--data-dir', [CompletionResultType]::ParameterName, 'specify the data directory')
            [CompletionResult]::new('--log-level', '--log-level', [CompletionResultType]::ParameterName, 'base log level for every component')
            [CompletionResult]::new('--log-file-rotation', '--log-file-rotation', [CompletionResultType]::ParameterName, 'rate at which new log files are generated')
            [CompletionResult]::new('--mfa-stored', '--mfa-stored', [CompletionResultType]::ParameterName, 'store the MFA key locally instead of copying a QR code')
            [CompletionResult]::new('--stdio-logs', '--stdio-logs', [CompletionResultType]::ParameterName, 'logs events to stdio')
            [CompletionResult]::new('--stdio-pretty', '--stdio-pretty', [CompletionResultType]::ParameterName, 'whether to pretty print stdio logs')
            [CompletionResult]::new('--stdio-json', '--stdio-json', [CompletionResultType]::ParameterName, 'whether to print stdio logs as json')
            [CompletionResult]::new('--json-logs', '--json-logs', [CompletionResultType]::ParameterName, 'persists JSON formatted log lines to <data-dir>/logs/')
            [CompletionResult]::new('--with-span-timing', '--with-span-timing', [CompletionResultType]::ParameterName, 'dictates whether timing information should be logged')
            [CompletionResult]::new('--log-size', '--log-size', [CompletionResultType]::ParameterName, 'whether storage sizes are logged')
            [CompletionResult]::new('-h', '-h', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')')
            [CompletionResult]::new('--help', '--help', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')')
            [CompletionResult]::new('-V', '-V ', [CompletionResultType]::ParameterName, 'Print version')
            [CompletionResult]::new('--version', '--version', [CompletionResultType]::ParameterName, 'Print version')
            break
        }
        'ordinaryd;api' {
            [CompletionResult]::new('--environment', '--environment', [CompletionResultType]::ParameterName, 'environment (e.g production, development, staging)')
            [CompletionResult]::new('--storage-size', '--storage-size', [CompletionResultType]::ParameterName, 'Storage size in bytes (rounded up to nearest OS page size)')
            [CompletionResult]::new('--provision', '--provision', [CompletionResultType]::ParameterName, 'what mode TLS certs should be provisioned in')
            [CompletionResult]::new('--port', '--port', [CompletionResultType]::ParameterName, 'specify HTTP(s) port for server')
            [CompletionResult]::new('--redirect-port', '--redirect-port', [CompletionResultType]::ParameterName, 'specify HTTP port for server when running in secure mode')
            [CompletionResult]::new('--redacted-header-hash', '--redacted-header-hash', [CompletionResultType]::ParameterName, '"none" | "blake2" | "blake3"')
            [CompletionResult]::new('--log-sync-interval-min', '--log-sync-interval-min', [CompletionResultType]::ParameterName, 'min duration between log indexing operations. (seconds)')
            [CompletionResult]::new('--log-sync-interval-max', '--log-sync-interval-max', [CompletionResultType]::ParameterName, 'duration between log indexing operations. (seconds)')
            [CompletionResult]::new('--log-max-ttl-days', '--log-max-ttl-days', [CompletionResultType]::ParameterName, 'max period of time logs are indexed/stored')
            [CompletionResult]::new('--data-dir', '--data-dir', [CompletionResultType]::ParameterName, 'specify the data directory')
            [CompletionResult]::new('--log-level', '--log-level', [CompletionResultType]::ParameterName, 'base log level for every component')
            [CompletionResult]::new('--log-file-rotation', '--log-file-rotation', [CompletionResultType]::ParameterName, 'rate at which new log files are generated')
            [CompletionResult]::new('--insecure', '--insecure', [CompletionResultType]::ParameterName, 'run without HTTPS')
            [CompletionResult]::new('--insecure-cookies', '--insecure-cookies', [CompletionResultType]::ParameterName, 'run with insecure cookies')
            [CompletionResult]::new('--log-headers', '--log-headers', [CompletionResultType]::ParameterName, 'whether HTTP request and response headers are logged')
            [CompletionResult]::new('--log-ips', '--log-ips', [CompletionResultType]::ParameterName, 'whether IP Addresses are logged with HTTP requests')
            [CompletionResult]::new('--dedicated-ports', '--dedicated-ports', [CompletionResultType]::ParameterName, 'give each app its own port')
            [CompletionResult]::new('--log-index', '--log-index', [CompletionResultType]::ParameterName, 'whether to index logs so they can be queried')
            [CompletionResult]::new('--swagger', '--swagger', [CompletionResultType]::ParameterName, 'Storage size in bytes (rounded up to nearest OS page size)')
            [CompletionResult]::new('--stdio-logs', '--stdio-logs', [CompletionResultType]::ParameterName, 'logs events to stdio')
            [CompletionResult]::new('--stdio-pretty', '--stdio-pretty', [CompletionResultType]::ParameterName, 'whether to pretty print stdio logs')
            [CompletionResult]::new('--stdio-json', '--stdio-json', [CompletionResultType]::ParameterName, 'whether to print stdio logs as json')
            [CompletionResult]::new('--json-logs', '--json-logs', [CompletionResultType]::ParameterName, 'persists JSON formatted log lines to <data-dir>/logs/')
            [CompletionResult]::new('--with-span-timing', '--with-span-timing', [CompletionResultType]::ParameterName, 'dictates whether timing information should be logged')
            [CompletionResult]::new('--log-size', '--log-size', [CompletionResultType]::ParameterName, 'whether storage sizes are logged')
            [CompletionResult]::new('-h', '-h', [CompletionResultType]::ParameterName, 'Print help')
            [CompletionResult]::new('--help', '--help', [CompletionResultType]::ParameterName, 'Print help')
            [CompletionResult]::new('-V', '-V ', [CompletionResultType]::ParameterName, 'Print version')
            [CompletionResult]::new('--version', '--version', [CompletionResultType]::ParameterName, 'Print version')
            break
        }
        'ordinaryd;app' {
            [CompletionResult]::new('--provision', '--provision', [CompletionResultType]::ParameterName, 'what mode TLS certs should be provisioned in')
            [CompletionResult]::new('--port', '--port', [CompletionResultType]::ParameterName, 'specify HTTP(s) port for server')
            [CompletionResult]::new('--redirect-port', '--redirect-port', [CompletionResultType]::ParameterName, 'specify HTTP port for server when running in secure mode')
            [CompletionResult]::new('--redacted-header-hash', '--redacted-header-hash', [CompletionResultType]::ParameterName, '"none" | "blake2" | "blake3"')
            [CompletionResult]::new('--project-dir', '--project-dir', [CompletionResultType]::ParameterName, 'for running a standalone project. (project must already be built)')
            [CompletionResult]::new('--domain-override', '--domain-override', [CompletionResultType]::ParameterName, 'use a different domain than what''s in the `ordinary.json`')
            [CompletionResult]::new('--data-dir', '--data-dir', [CompletionResultType]::ParameterName, 'specify the data directory')
            [CompletionResult]::new('--log-level', '--log-level', [CompletionResultType]::ParameterName, 'base log level for every component')
            [CompletionResult]::new('--log-file-rotation', '--log-file-rotation', [CompletionResultType]::ParameterName, 'rate at which new log files are generated')
            [CompletionResult]::new('--insecure', '--insecure', [CompletionResultType]::ParameterName, 'run without HTTPS')
            [CompletionResult]::new('--insecure-cookies', '--insecure-cookies', [CompletionResultType]::ParameterName, 'run with insecure cookies')
            [CompletionResult]::new('--log-headers', '--log-headers', [CompletionResultType]::ParameterName, 'whether HTTP request and response headers are logged')
            [CompletionResult]::new('--log-ips', '--log-ips', [CompletionResultType]::ParameterName, 'whether IP Addresses are logged with HTTP requests')
            [CompletionResult]::new('--stdio-logs', '--stdio-logs', [CompletionResultType]::ParameterName, 'logs events to stdio')
            [CompletionResult]::new('--stdio-pretty', '--stdio-pretty', [CompletionResultType]::ParameterName, 'whether to pretty print stdio logs')
            [CompletionResult]::new('--stdio-json', '--stdio-json', [CompletionResultType]::ParameterName, 'whether to print stdio logs as json')
            [CompletionResult]::new('--json-logs', '--json-logs', [CompletionResultType]::ParameterName, 'persists JSON formatted log lines to <data-dir>/logs/')
            [CompletionResult]::new('--with-span-timing', '--with-span-timing', [CompletionResultType]::ParameterName, 'dictates whether timing information should be logged')
            [CompletionResult]::new('--log-size', '--log-size', [CompletionResultType]::ParameterName, 'whether storage sizes are logged')
            [CompletionResult]::new('-h', '-h', [CompletionResultType]::ParameterName, 'Print help')
            [CompletionResult]::new('--help', '--help', [CompletionResultType]::ParameterName, 'Print help')
            [CompletionResult]::new('-V', '-V ', [CompletionResultType]::ParameterName, 'Print version')
            [CompletionResult]::new('--version', '--version', [CompletionResultType]::ParameterName, 'Print version')
            break
        }
        'ordinaryd;help' {
            [CompletionResult]::new('init', 'init', [CompletionResultType]::ParameterValue, 'initialize the environment for an Ordinary API server')
            [CompletionResult]::new('api', 'api', [CompletionResultType]::ParameterValue, 'start the Ordinary API server')
            [CompletionResult]::new('app', 'app', [CompletionResultType]::ParameterValue, 'start an Ordinary Application server')
            [CompletionResult]::new('help', 'help', [CompletionResultType]::ParameterValue, 'Print this message or the help of the given subcommand(s)')
            break
        }
        'ordinaryd;help;init' {
            break
        }
        'ordinaryd;help;api' {
            break
        }
        'ordinaryd;help;app' {
            break
        }
        'ordinaryd;help;help' {
            break
        }
    })

    $completions.Where{ $_.CompletionText -like "$wordToComplete*" } |
        Sort-Object -Property ListItemText
}
