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

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

    $commandElements = $commandAst.CommandElements
    $command = @(
        'amaru'
        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) {
        'amaru' {
            [CompletionResult]::new('--color', '--color', [CompletionResultType]::ParameterName, 'color')
            [CompletionResult]::new('--with-open-telemetry', '--with-open-telemetry', [CompletionResultType]::ParameterName, 'with-open-telemetry')
            [CompletionResult]::new('--with-json-traces', '--with-json-traces', [CompletionResultType]::ParameterName, 'with-json-traces')
            [CompletionResult]::new('-q', '-q', [CompletionResultType]::ParameterName, 'Do not initialize tracing library')
            [CompletionResult]::new('--quiet', '--quiet', [CompletionResultType]::ParameterName, 'Do not initialize tracing library')
            [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('bootstrap', 'bootstrap', [CompletionResultType]::ParameterValue, 'Bootstrap the node with needed data.')
            [CompletionResult]::new('dump-chain-db', 'dump-chain-db', [CompletionResultType]::ParameterValue, 'Dump the content of the chain database for troubleshooting purposes')
            [CompletionResult]::new('remove-validation-status', 'remove-validation-status', [CompletionResultType]::ParameterValue, 'Remove the validation status of the given blocks from the chain database')
            [CompletionResult]::new('remove-chain', 'remove-chain', [CompletionResultType]::ParameterValue, 'Remove the given chain fragment from the chain database')
            [CompletionResult]::new('dump-traces-schema', 'dump-traces-schema', [CompletionResultType]::ParameterValue, 'Dump all registered trace schemas as JSON Schema')
            [CompletionResult]::new('fetch-chain-headers', 'fetch-chain-headers', [CompletionResultType]::ParameterValue, 'Fetch specified headers')
            [CompletionResult]::new('create-snapshots', 'create-snapshots', [CompletionResultType]::ParameterValue, 'Create the three consecutive epoch snapshots needed for bootstrap')
            [CompletionResult]::new('shell-completions', 'shell-completions', [CompletionResultType]::ParameterValue, 'shell-completions')
            [CompletionResult]::new('migrate-chain-db', 'migrate-chain-db', [CompletionResultType]::ParameterValue, 'Migrate the chain database to the current version')
            [CompletionResult]::new('reset-to-epoch', 'reset-to-epoch', [CompletionResultType]::ParameterValue, 'Reset the ledger database to the beginning of a specific epoch')
            [CompletionResult]::new('run', 'run', [CompletionResultType]::ParameterValue, 'Run the node in all its glory')
            [CompletionResult]::new('help', 'help', [CompletionResultType]::ParameterValue, 'Print this message or the help of the given subcommand(s)')
            break
        }
        'amaru;bootstrap' {
            [CompletionResult]::new('--chain-dir', '--chain-dir', [CompletionResultType]::ParameterName, 'Path of the chain on-disk storage')
            [CompletionResult]::new('--ledger-dir', '--ledger-dir', [CompletionResultType]::ParameterName, 'Path of the ledger on-disk storage')
            [CompletionResult]::new('--epoch', '--epoch', [CompletionResultType]::ParameterName, 'The target bootstrap epoch; this is the epoch Amaru will start from')
            [CompletionResult]::new('--network', '--network', [CompletionResultType]::ParameterName, 'Network to bootstrap the node for')
            [CompletionResult]::new('--consensus-security-param', '--consensus-security-param', [CompletionResultType]::ParameterName, 'The maximum depth of a rollback, also known as the security parameter ''k''')
            [CompletionResult]::new('--epoch-length-scale-factor', '--epoch-length-scale-factor', [CompletionResultType]::ParameterName, 'Multiplier applied to the `consensus_security_param` to determine the epoch length')
            [CompletionResult]::new('--active-slot-coeff-inverse', '--active-slot-coeff-inverse', [CompletionResultType]::ParameterName, 'Inverse of the active slot coefficient (i.e. 1/f);')
            [CompletionResult]::new('--max-lovelace-supply', '--max-lovelace-supply', [CompletionResultType]::ParameterName, 'Maximum supply of Ada, in lovelace (1 Ada = 1,000,000 Lovelace)')
            [CompletionResult]::new('--slots-per-kes-period', '--slots-per-kes-period', [CompletionResultType]::ParameterName, 'Number of slots for a single KES validity period')
            [CompletionResult]::new('--max-kes-evolution', '--max-kes-evolution', [CompletionResultType]::ParameterName, 'Maximum number of KES key evolution. Combined with SLOTS_PER_KES_PERIOD, these values indicates the validity period of a KES key before a new one is required')
            [CompletionResult]::new('--system-start', '--system-start', [CompletionResultType]::ParameterName, 'POSIX time (milliseconds) of the System Start')
            [CompletionResult]::new('-f', '-f', [CompletionResultType]::ParameterName, 'Forcefully erase and overwrite the ledger database if it already exists')
            [CompletionResult]::new('--force', '--force', [CompletionResultType]::ParameterName, 'Forcefully erase and overwrite the ledger database if it already exists')
            [CompletionResult]::new('--help-global-parameters', '--help-global-parameters', [CompletionResultType]::ParameterName, 'Show global network parameter overrides, for custom testnets')
            [CompletionResult]::new('-h', '-h', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')')
            [CompletionResult]::new('--help', '--help', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')')
            break
        }
        'amaru;dump-chain-db' {
            [CompletionResult]::new('--chain-dir', '--chain-dir', [CompletionResultType]::ParameterName, 'The path to the chain database to dump')
            [CompletionResult]::new('--network', '--network', [CompletionResultType]::ParameterName, 'Network for which we are importing headers')
            [CompletionResult]::new('-a', '-a', [CompletionResultType]::ParameterName, 'a')
            [CompletionResult]::new('--ancestors', '--ancestors', [CompletionResultType]::ParameterName, 'ancestors')
            [CompletionResult]::new('-c', '-c', [CompletionResultType]::ParameterName, 'c')
            [CompletionResult]::new('--children', '--children', [CompletionResultType]::ParameterName, 'children')
            [CompletionResult]::new('-H', '-H ', [CompletionResultType]::ParameterName, 'H')
            [CompletionResult]::new('--headers', '--headers', [CompletionResultType]::ParameterName, 'headers')
            [CompletionResult]::new('-p', '-p', [CompletionResultType]::ParameterName, 'p')
            [CompletionResult]::new('--parents-children', '--parents-children', [CompletionResultType]::ParameterName, 'parents-children')
            [CompletionResult]::new('-n', '-n', [CompletionResultType]::ParameterName, 'n')
            [CompletionResult]::new('--nonces', '--nonces', [CompletionResultType]::ParameterName, 'nonces')
            [CompletionResult]::new('-B', '-B ', [CompletionResultType]::ParameterName, 'B')
            [CompletionResult]::new('--blocks', '--blocks', [CompletionResultType]::ParameterName, 'blocks')
            [CompletionResult]::new('-b', '-b', [CompletionResultType]::ParameterName, 'b')
            [CompletionResult]::new('--best-chain', '--best-chain', [CompletionResultType]::ParameterName, 'best-chain')
            [CompletionResult]::new('-f', '-f', [CompletionResultType]::ParameterName, 'f')
            [CompletionResult]::new('--find-best-candidate', '--find-best-candidate', [CompletionResultType]::ParameterName, 'find-best-candidate')
            [CompletionResult]::new('-h', '-h', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')')
            [CompletionResult]::new('--help', '--help', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')')
            break
        }
        'amaru;remove-validation-status' {
            [CompletionResult]::new('--chain-dir', '--chain-dir', [CompletionResultType]::ParameterName, 'The path to the chain store database to remove the validation status from')
            [CompletionResult]::new('--network', '--network', [CompletionResultType]::ParameterName, 'Network of the underlying chain database')
            [CompletionResult]::new('-h', '-h', [CompletionResultType]::ParameterName, 'Print help')
            [CompletionResult]::new('--help', '--help', [CompletionResultType]::ParameterName, 'Print help')
            break
        }
        'amaru;remove-chain' {
            [CompletionResult]::new('--from-point', '--from-point', [CompletionResultType]::ParameterName, 'The point from which onward to remove the chain')
            [CompletionResult]::new('--chain-dir', '--chain-dir', [CompletionResultType]::ParameterName, 'The path to the chain store database to remove the validation status from')
            [CompletionResult]::new('--network', '--network', [CompletionResultType]::ParameterName, 'Network of the underlying chain database')
            [CompletionResult]::new('--only-blocks', '--only-blocks', [CompletionResultType]::ParameterName, 'Remove only blocks')
            [CompletionResult]::new('--only-validation-results', '--only-validation-results', [CompletionResultType]::ParameterName, 'Remove only validation results')
            [CompletionResult]::new('-h', '-h', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')')
            [CompletionResult]::new('--help', '--help', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')')
            break
        }
        'amaru;dump-traces-schema' {
            [CompletionResult]::new('-c', '-c', [CompletionResultType]::ParameterName, 'Compact JSON output (no pretty-printing)')
            [CompletionResult]::new('--compact', '--compact', [CompletionResultType]::ParameterName, 'Compact JSON output (no pretty-printing)')
            [CompletionResult]::new('-h', '-h', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')')
            [CompletionResult]::new('--help', '--help', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')')
            break
        }
        'amaru;fetch-chain-headers' {
            [CompletionResult]::new('--headers-dir', '--headers-dir', [CompletionResultType]::ParameterName, 'Path where to store fetched headers')
            [CompletionResult]::new('--network', '--network', [CompletionResultType]::ParameterName, 'Network to fetch chain headers from')
            [CompletionResult]::new('--parent', '--parent', [CompletionResultType]::ParameterName, 'Parent point of the header to fetch')
            [CompletionResult]::new('--peer-address', '--peer-address', [CompletionResultType]::ParameterName, 'Address of the node to connect to for retrieving chain data')
            [CompletionResult]::new('-h', '-h', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')')
            [CompletionResult]::new('--help', '--help', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')')
            break
        }
        'amaru;create-snapshots' {
            [CompletionResult]::new('--network', '--network', [CompletionResultType]::ParameterName, 'The target network to choose from')
            [CompletionResult]::new('--epoch', '--epoch', [CompletionResultType]::ParameterName, 'The target epoch *after* bootstrap')
            [CompletionResult]::new('--dist-dir', '--dist-dir', [CompletionResultType]::ParameterName, 'Distribution directory used for metadata, caches and temporary work files')
            [CompletionResult]::new('--snapshot-dir', '--snapshot-dir', [CompletionResultType]::ParameterName, 'Directory where snapshot archives and materialized snapshot directories are written')
            [CompletionResult]::new('--cardano-node-config-dir', '--cardano-node-config-dir', [CompletionResultType]::ParameterName, 'Directory containing the cardano-node config.json and genesis files')
            [CompletionResult]::new('--cardano-node-db', '--cardano-node-db', [CompletionResultType]::ParameterName, 'Use an existing local cardano-node database instead of downloading via Mithril')
            [CompletionResult]::new('--snapshot', '--snapshot', [CompletionResultType]::ParameterName, 'An optional list of three snapshot points. The option may be repeated')
            [CompletionResult]::new('-f', '-f', [CompletionResultType]::ParameterName, 'Forcefully erase requested generated snapshot outputs and regenerate them')
            [CompletionResult]::new('--force', '--force', [CompletionResultType]::ParameterName, 'Forcefully erase requested generated snapshot outputs and regenerate them')
            [CompletionResult]::new('-h', '-h', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')')
            [CompletionResult]::new('--help', '--help', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')')
            break
        }
        'amaru;shell-completions' {
            [CompletionResult]::new('--output-dir', '--output-dir', [CompletionResultType]::ParameterName, 'output-dir')
            [CompletionResult]::new('-h', '-h', [CompletionResultType]::ParameterName, 'Print help')
            [CompletionResult]::new('--help', '--help', [CompletionResultType]::ParameterName, 'Print help')
            break
        }
        'amaru;migrate-chain-db' {
            [CompletionResult]::new('--chain-dir', '--chain-dir', [CompletionResultType]::ParameterName, 'The path to the chain database to migrate')
            [CompletionResult]::new('--network', '--network', [CompletionResultType]::ParameterName, 'Underlying network of the database to migrate')
            [CompletionResult]::new('-h', '-h', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')')
            [CompletionResult]::new('--help', '--help', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')')
            break
        }
        'amaru;reset-to-epoch' {
            [CompletionResult]::new('--ledger-dir', '--ledger-dir', [CompletionResultType]::ParameterName, 'The path to the ledger database to reset')
            [CompletionResult]::new('--network', '--network', [CompletionResultType]::ParameterName, 'Network of the underlying chain database')
            [CompletionResult]::new('-h', '-h', [CompletionResultType]::ParameterName, 'Print help')
            [CompletionResult]::new('--help', '--help', [CompletionResultType]::ParameterName, 'Print help')
            break
        }
        'amaru;run' {
            [CompletionResult]::new('--network', '--network', [CompletionResultType]::ParameterName, 'The target network to run against')
            [CompletionResult]::new('--chain-dir', '--chain-dir', [CompletionResultType]::ParameterName, 'Path of the chain on-disk storage')
            [CompletionResult]::new('--ledger-dir', '--ledger-dir', [CompletionResultType]::ParameterName, 'Path of the ledger on-disk storage')
            [CompletionResult]::new('--listen-address', '--listen-address', [CompletionResultType]::ParameterName, 'The address to listen on for incoming connections')
            [CompletionResult]::new('--submit-api-address', '--submit-api-address', [CompletionResultType]::ParameterName, 'Address for the HTTP transaction submit API')
            [CompletionResult]::new('--peer-address', '--peer-address', [CompletionResultType]::ParameterName, 'Upstream peer addresses to synchronize from')
            [CompletionResult]::new('--upstream-peers', '--upstream-peers', [CompletionResultType]::ParameterName, 'The number of upstream peers to connect to')
            [CompletionResult]::new('--downstream-peers', '--downstream-peers', [CompletionResultType]::ParameterName, 'The maximum number of downstream peers allowed to connect')
            [CompletionResult]::new('--max-extra-ledger-snapshots', '--max-extra-ledger-snapshots', [CompletionResultType]::ParameterName, 'The maximum number of additional ledger snapshots to keep around')
            [CompletionResult]::new('--peer-removal-cooldown-secs', '--peer-removal-cooldown-secs', [CompletionResultType]::ParameterName, 'After removing a misbehaving upstream peer, wait this many seconds before allowing it to be re-added')
            [CompletionResult]::new('--pid-file', '--pid-file', [CompletionResultType]::ParameterName, 'Path to the PID file managed by Amaru')
            [CompletionResult]::new('--trace-buffer', '--trace-buffer', [CompletionResultType]::ParameterName, 'Stage graph trace buffer: `min_entries,max_total_bytes` (e.g. `100,1000000`)')
            [CompletionResult]::new('--dump-trace-buffer', '--dump-trace-buffer', [CompletionResultType]::ParameterName, 'Concatenate raw CBOR trace entries to this file when the node shuts down')
            [CompletionResult]::new('--era-history', '--era-history', [CompletionResultType]::ParameterName, 'Path to a JSON era history file overriding the network default')
            [CompletionResult]::new('--consensus-security-param', '--consensus-security-param', [CompletionResultType]::ParameterName, 'The maximum depth of a rollback, also known as the security parameter ''k''')
            [CompletionResult]::new('--epoch-length-scale-factor', '--epoch-length-scale-factor', [CompletionResultType]::ParameterName, 'Multiplier applied to the `consensus_security_param` to determine the epoch length')
            [CompletionResult]::new('--active-slot-coeff-inverse', '--active-slot-coeff-inverse', [CompletionResultType]::ParameterName, 'Inverse of the active slot coefficient (i.e. 1/f);')
            [CompletionResult]::new('--max-lovelace-supply', '--max-lovelace-supply', [CompletionResultType]::ParameterName, 'Maximum supply of Ada, in lovelace (1 Ada = 1,000,000 Lovelace)')
            [CompletionResult]::new('--slots-per-kes-period', '--slots-per-kes-period', [CompletionResultType]::ParameterName, 'Number of slots for a single KES validity period')
            [CompletionResult]::new('--max-kes-evolution', '--max-kes-evolution', [CompletionResultType]::ParameterName, 'Maximum number of KES key evolution. Combined with SLOTS_PER_KES_PERIOD, these values indicates the validity period of a KES key before a new one is required')
            [CompletionResult]::new('--system-start', '--system-start', [CompletionResultType]::ParameterName, 'POSIX time (milliseconds) of the System Start')
            [CompletionResult]::new('--migrate-chain-db', '--migrate-chain-db', [CompletionResultType]::ParameterName, 'Flag to automatically migrate the chain database if needed')
            [CompletionResult]::new('--help-global-parameters', '--help-global-parameters', [CompletionResultType]::ParameterName, 'Show global network parameter overrides, for custom testnets')
            [CompletionResult]::new('-h', '-h', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')')
            [CompletionResult]::new('--help', '--help', [CompletionResultType]::ParameterName, 'Print help (see more with ''--help'')')
            break
        }
        'amaru;help' {
            [CompletionResult]::new('bootstrap', 'bootstrap', [CompletionResultType]::ParameterValue, 'Bootstrap the node with needed data.')
            [CompletionResult]::new('dump-chain-db', 'dump-chain-db', [CompletionResultType]::ParameterValue, 'Dump the content of the chain database for troubleshooting purposes')
            [CompletionResult]::new('remove-validation-status', 'remove-validation-status', [CompletionResultType]::ParameterValue, 'Remove the validation status of the given blocks from the chain database')
            [CompletionResult]::new('remove-chain', 'remove-chain', [CompletionResultType]::ParameterValue, 'Remove the given chain fragment from the chain database')
            [CompletionResult]::new('dump-traces-schema', 'dump-traces-schema', [CompletionResultType]::ParameterValue, 'Dump all registered trace schemas as JSON Schema')
            [CompletionResult]::new('fetch-chain-headers', 'fetch-chain-headers', [CompletionResultType]::ParameterValue, 'Fetch specified headers')
            [CompletionResult]::new('create-snapshots', 'create-snapshots', [CompletionResultType]::ParameterValue, 'Create the three consecutive epoch snapshots needed for bootstrap')
            [CompletionResult]::new('shell-completions', 'shell-completions', [CompletionResultType]::ParameterValue, 'shell-completions')
            [CompletionResult]::new('migrate-chain-db', 'migrate-chain-db', [CompletionResultType]::ParameterValue, 'Migrate the chain database to the current version')
            [CompletionResult]::new('reset-to-epoch', 'reset-to-epoch', [CompletionResultType]::ParameterValue, 'Reset the ledger database to the beginning of a specific epoch')
            [CompletionResult]::new('run', 'run', [CompletionResultType]::ParameterValue, 'Run the node in all its glory')
            [CompletionResult]::new('help', 'help', [CompletionResultType]::ParameterValue, 'Print this message or the help of the given subcommand(s)')
            break
        }
        'amaru;help;bootstrap' {
            break
        }
        'amaru;help;dump-chain-db' {
            break
        }
        'amaru;help;remove-validation-status' {
            break
        }
        'amaru;help;remove-chain' {
            break
        }
        'amaru;help;dump-traces-schema' {
            break
        }
        'amaru;help;fetch-chain-headers' {
            break
        }
        'amaru;help;create-snapshots' {
            break
        }
        'amaru;help;shell-completions' {
            break
        }
        'amaru;help;migrate-chain-db' {
            break
        }
        'amaru;help;reset-to-epoch' {
            break
        }
        'amaru;help;run' {
            break
        }
        'amaru;help;help' {
            break
        }
    })

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