#compdef xfr

autoload -U is-at-least

_xfr() {
    typeset -A opt_args
    typeset -a _arguments_options
    local ret=1

    if is-at-least 5.2; then
        _arguments_options=(-s -S -C)
    else
        _arguments_options=(-s -C)
    fi

    local context curcontext="$curcontext" state line
    _arguments "${_arguments_options[@]}" : \
'--completions=[Generate shell completions]:SHELL:(bash zsh fish powershell elvish)' \
'-p+[Server/client port]:PORT:_default' \
'--port=[Server/client port]:PORT:_default' \
'-t+[Test duration. Bare integers are seconds (\`-t 10\`), or use unit suffixes (\`10s\`, \`1min\`, \`500ms\`). Use 0 for infinite]:TIME:_default' \
'--time=[Test duration. Bare integers are seconds (\`-t 10\`), or use unit suffixes (\`10s\`, \`1min\`, \`500ms\`). Use 0 for infinite]:TIME:_default' \
'-b+[Target bitrate (e.g., 1G, 100M). Applies to TCP and UDP. 0 = unlimited]:BITRATE:_default' \
'--bitrate=[Target bitrate (e.g., 1G, 100M). Applies to TCP and UDP. 0 = unlimited]:BITRATE:_default' \
'-P+[Number of parallel streams (1-128)]:PARALLEL:_default' \
'--parallel=[Number of parallel streams (1-128)]:PARALLEL:_default' \
'-o+[Output file]:OUTPUT:_files' \
'--output=[Output file]:OUTPUT:_files' \
'--theme=[Color theme (default, kawaii, cyber, dracula, monochrome, matrix, nord, gruvbox, catppuccin, tokyo_night, solarized)]:THEME:_default' \
'-i+[Report interval in seconds]:INTERVAL:_default' \
'--interval=[Report interval in seconds]:INTERVAL:_default' \
'--omit=[Omit first N seconds from interval output (TCP ramp-up)]:OMIT:_default' \
'--congestion=[TCP congestion control algorithm (e.g. cubic, bbr, reno)]:ALGO:_default' \
'--dscp=[DSCP/TOS marking\: raw TOS byte (0-255) or DSCP name (EF, AF11, CS1, etc.)]:VALUE:_default' \
'-w+[Socket buffer size for TCP (SO_SNDBUF/SO_RCVBUF) and UDP (SO_SNDBUF/SO_RCVBUF on both ends), e.g., 512K, 1M, 16M. When unset, TCP uses kernel autotuning and UDP uses the kernel default]:WINDOW:_default' \
'--window=[Socket buffer size for TCP (SO_SNDBUF/SO_RCVBUF) and UDP (SO_SNDBUF/SO_RCVBUF on both ends), e.g., 512K, 1M, 16M. When unset, TCP uses kernel autotuning and UDP uses the kernel default]:WINDOW:_default' \
'--timestamp-format=[Timestamp format for interval output (relative, iso8601, unix)]:TIMESTAMP_FORMAT:_default' \
'--log-file=[Log file path (e.g., "~/.config/xfr/xfr.log")]:LOG_FILE:_default' \
'--log-level=[Log level (error, warn, info, debug, trace)]:LOG_LEVEL:_default' \
'--psk=[Pre-shared key for server authentication]:PSK:_default' \
'--psk-file=[Read PSK from file]:PSK_FILE:_files' \
'--bind=[Local address to bind to (e.g., 192.168.1.100 or 192.168.1.100\:0)]:ADDR:_default' \
'--cport=[Client source port for firewall traversal (UDP/QUIC/TCP data streams)]:PORT:_default' \
'(-Q --quic)-u[UDP mode]' \
'(-Q --quic)--udp[UDP mode]' \
'(-u --udp)-Q[QUIC mode (encrypted, multiplexed streams)]' \
'(-u --udp)--quic[QUIC mode (encrypted, multiplexed streams)]' \
'(--bidir)-R[Reverse direction (server sends to client)]' \
'(--bidir)--reverse[Reverse direction (server sends to client)]' \
'(-R --reverse)--bidir[Bidirectional test]' \
'(--csv)--json[JSON output]' \
'(--csv)--json-stream[JSON streaming output (one object per line)]' \
'(--json --json-stream)--csv[CSV output]' \
'-q[Quiet mode - suppress interval output, show only summary]' \
'--quiet[Quiet mode - suppress interval output, show only summary]' \
'--no-tui[Disable TUI]' \
'--tcp-nodelay[Disable Nagle algorithm]' \
'-4[Force IPv4 only]' \
'--ipv4[Force IPv4 only]' \
'-6[Force IPv6 only]' \
'--ipv6[Force IPv6 only]' \
'(-u --udp -Q --quic)--mptcp[MPTCP mode (Multi-Path TCP, Linux 5.6+)]' \
'(--zeros)--random[Use random payload data (default for TCP/UDP client-sent traffic)]' \
'(--random)--zeros[Use zero-filled payload data instead of random bytes]' \
'-h[Print help]' \
'--help[Print help]' \
'-V[Print version]' \
'--version[Print version]' \
'::host -- Target host for client mode:_default' \
":: :_xfr_commands" \
"*::: :->xfr" \
&& ret=0
    case $state in
    (xfr)
        words=($line[2] "${words[@]}")
        (( CURRENT += 1 ))
        curcontext="${curcontext%:*:*}:xfr-command-$line[2]:"
        case $line[2] in
            (serve)
_arguments "${_arguments_options[@]}" : \
'-p+[Server port]:PORT:_default' \
'--port=[Server port]:PORT:_default' \
'--max-duration=[Maximum test duration (server-side limit). Bare integers are seconds (\`60\`); unit suffixes also accepted (\`60s\`, \`5min\`)]:MAX_DURATION:_default' \
'--push-gateway=[Prometheus push gateway URL (e.g., http\://pushgateway\:9091)]:PUSH_GATEWAY:_default' \
'--log-file=[Log file path (e.g., "~/.config/xfr/xfr.log")]:LOG_FILE:_default' \
'--log-level=[Log level (error, warn, info, debug, trace)]:LOG_LEVEL:_default' \
'--psk=[Pre-shared key for authentication]:PSK:_default' \
'--psk-file=[Read PSK from file]:PSK_FILE:_files' \
'--rate-limit=[Max concurrent tests per IP (rate limiting)]:RATE_LIMIT:_default' \
'--rate-limit-window=[Rate limit time window. Bare integers are seconds (\`60\`); must be greater than 0]:RATE_LIMIT_WINDOW:_default' \
'*--allow=[Allow IP/subnet (can be repeated)]:ALLOW:_default' \
'*--deny=[Deny IP/subnet (can be repeated)]:DENY:_default' \
'--acl-file=[ACL rules file]:ACL_FILE:_files' \
'-B+[Bind to specific address (e.g., 192.168.1.1, \:\:1)]:BIND:_default' \
'--bind=[Bind to specific address (e.g., 192.168.1.1, \:\:1)]:BIND:_default' \
'--one-off[Exit after one test]' \
'--tui[Enable TUI dashboard]' \
'-4[Force IPv4 only]' \
'--ipv4[Force IPv4 only]' \
'-6[Force IPv6 only]' \
'--ipv6[Force IPv6 only]' \
'--no-mdns[Disable mDNS service registration]' \
'-h[Print help]' \
'--help[Print help]' \
&& ret=0
;;
(diff)
_arguments "${_arguments_options[@]}" : \
'--threshold=[Regression threshold percentage]:THRESHOLD:_default' \
'-h[Print help]' \
'--help[Print help]' \
':baseline -- Baseline result file:_files' \
':current -- Current result file:_files' \
&& ret=0
;;
(discover)
_arguments "${_arguments_options[@]}" : \
'--timeout=[Discovery timeout. Bare integers are seconds (\`5\`); unit suffixes also accepted (\`5s\`, \`500ms\`)]:TIMEOUT:_default' \
'-h[Print help]' \
'--help[Print help]' \
&& ret=0
;;
(help)
_arguments "${_arguments_options[@]}" : \
":: :_xfr__subcmd__help_commands" \
"*::: :->help" \
&& ret=0

    case $state in
    (help)
        words=($line[1] "${words[@]}")
        (( CURRENT += 1 ))
        curcontext="${curcontext%:*:*}:xfr-help-command-$line[1]:"
        case $line[1] in
            (serve)
_arguments "${_arguments_options[@]}" : \
&& ret=0
;;
(diff)
_arguments "${_arguments_options[@]}" : \
&& ret=0
;;
(discover)
_arguments "${_arguments_options[@]}" : \
&& ret=0
;;
(help)
_arguments "${_arguments_options[@]}" : \
&& ret=0
;;
        esac
    ;;
esac
;;
        esac
    ;;
esac
}

(( $+functions[_xfr_commands] )) ||
_xfr_commands() {
    local commands; commands=(
'serve:Start server mode' \
'diff:Compare two test results' \
'discover:Discover xfr servers on LAN' \
'help:Print this message or the help of the given subcommand(s)' \
    )
    _describe -t commands 'xfr commands' commands "$@"
}
(( $+functions[_xfr__subcmd__diff_commands] )) ||
_xfr__subcmd__diff_commands() {
    local commands; commands=()
    _describe -t commands 'xfr diff commands' commands "$@"
}
(( $+functions[_xfr__subcmd__discover_commands] )) ||
_xfr__subcmd__discover_commands() {
    local commands; commands=()
    _describe -t commands 'xfr discover commands' commands "$@"
}
(( $+functions[_xfr__subcmd__help_commands] )) ||
_xfr__subcmd__help_commands() {
    local commands; commands=(
'serve:Start server mode' \
'diff:Compare two test results' \
'discover:Discover xfr servers on LAN' \
'help:Print this message or the help of the given subcommand(s)' \
    )
    _describe -t commands 'xfr help commands' commands "$@"
}
(( $+functions[_xfr__subcmd__help__subcmd__diff_commands] )) ||
_xfr__subcmd__help__subcmd__diff_commands() {
    local commands; commands=()
    _describe -t commands 'xfr help diff commands' commands "$@"
}
(( $+functions[_xfr__subcmd__help__subcmd__discover_commands] )) ||
_xfr__subcmd__help__subcmd__discover_commands() {
    local commands; commands=()
    _describe -t commands 'xfr help discover commands' commands "$@"
}
(( $+functions[_xfr__subcmd__help__subcmd__help_commands] )) ||
_xfr__subcmd__help__subcmd__help_commands() {
    local commands; commands=()
    _describe -t commands 'xfr help help commands' commands "$@"
}
(( $+functions[_xfr__subcmd__help__subcmd__serve_commands] )) ||
_xfr__subcmd__help__subcmd__serve_commands() {
    local commands; commands=()
    _describe -t commands 'xfr help serve commands' commands "$@"
}
(( $+functions[_xfr__subcmd__serve_commands] )) ||
_xfr__subcmd__serve_commands() {
    local commands; commands=()
    _describe -t commands 'xfr serve commands' commands "$@"
}

if [ "$funcstack[1]" = "_xfr" ]; then
    _xfr "$@"
else
    compdef _xfr xfr
fi
