# SPDX-License-Identifier: LGPL-2.1-or-later
# shellcheck shell=bash

_ukify_completion() {
    local cur="$2" word option="" verb="" prefix=""
    local line="$COMP_LINE" previous="" wordbreak_prefix kind=""
    local -i i position=0 cword=-1 continue_options=1
    local -a words=()
    local -a options=(--version --summary --config -c --linux --os-release --cmdline --initrd --efifw --microcode --splash --devicetree --devicetree-auto --hwids --uname --sbat --pcrpkey --section --profile --join-profile --sign-profile --pcrsig --join-pcrsig --efi-arch --stub --pcr-banks --signing-engine --signing-provider --certificate-provider --signtool --secureboot-private-key --secureboot-certificate --secureboot-certificate-common-name --secureboot-certificate-dir --secureboot-certificate-name --secureboot-certificate-validity --sign-kernel --no-sign-kernel --sign-initrd-pcrs --no-sign-initrd-pcrs --pcr-private-key --pcr-public-key --pcr-certificate --phases --policyref --tools --output -o --measure --no-measure --policy-digest --no-policy-digest --json -j --all -h --help)
    local -a verbs=(build genkey inspect completion)
    local -a shells=(bash zsh)
    local -A choices=([--efi-arch]='ia32 x64 arm aa64 riscv32 riscv64 loongarch32 loongarch64' [--signtool]='sbsign pesign systemd-sbsign' [--json]='pretty short off')
    local -A arguments=([--config]=file [-c]=file [--linux]=file [--os-release]=at-file [--cmdline]=at-file [--initrd]=file [--efifw]=directory [--microcode]=file [--splash]=file [--devicetree]=file [--devicetree-auto]=file [--hwids]=directory [--uname]=default [--sbat]=at-file [--pcrpkey]=file [--section]=section-file [--profile]=at-file [--join-profile]=file [--sign-profile]=default [--pcrsig]=at-file [--join-pcrsig]=file [--efi-arch]=default [--stub]=file [--pcr-banks]=default [--signing-engine]=default [--signing-provider]=default [--certificate-provider]=default [--signtool]=default [--secureboot-private-key]=file [--secureboot-certificate]=file [--secureboot-certificate-common-name]=default [--secureboot-certificate-dir]=directory [--secureboot-certificate-name]=default [--secureboot-certificate-validity]=default [--pcr-private-key]=file [--pcr-public-key]=file [--pcr-certificate]=file [--phases]=default [--policyref]=default [--tools]=directory [--output]=file [-o]=file [--json]=default)

    COMPREPLY=()

    # Rejoin separators split out by Bash, including the colon in NAME:@PATH.
    for ((i = 0; i <= COMP_CWORD; i++)); do
        word=${COMP_WORDS[i]}
        if ((i > 1)) && [[ $line != [[:blank:]]* ]] &&
            [[ $word =~ ^[=@:]+$ || $previous =~ ^[=@:]+$ ]]
        then
            words[cword]+=$word
        else
            cword=$((cword + 1))
            words[cword]=$word
        fi
        line=${line#*"$word"}
        previous=$word
    done

    wordbreak_prefix=${words[cword]%"$cur"}
    cur=${words[cword]}

    for ((i = 1; i < cword; i++)); do
        word=${words[i]}
        if [[ -n $option ]]; then
            option=""
        elif ((continue_options)) && [[ $word == -- ]]; then
            continue_options=0
        elif ((continue_options)) && [[ $word == -* ]]; then
            if [[ $word != *=* && -n ${arguments[$word]-} ]]; then
                option=$word
            fi
        else
            [[ -n $verb ]] || verb=$word
            position=$((position + 1))
        fi
    done

    if ((continue_options)) && [[ -z $option && $cur == --*=* ]]; then
        option=${cur%%=*}
        prefix=${option}=
        cur=${cur#*=}
    elif ((continue_options)) && [[ -z $option && $cur == -* ]]; then
        readarray -t COMPREPLY < <(compgen -W "${options[*]}" -- "$cur")
        return
    fi

    if [[ -n $option ]]; then
        kind=${arguments[$option]-}
        if [[ $kind == at-file || $kind == section-file ]]; then
            # Undo Readline's quoting of @ when continuing a previously completed path.
            cur=${cur/\\@/@}
        fi
        if [[ $kind == section-file ]]; then
            [[ $cur == *:* ]] || return
            prefix+=${cur%%:*}:
            cur=${cur#*:}
            if [[ $cur == text@* || $cur == binary@* ]]; then
                prefix+=${cur%%@*}
                cur=@${cur#*@}
            fi
            kind=at-file
        fi
        if [[ $kind == at-file ]]; then
            [[ $cur == @* ]] || return
            prefix+=@
            cur=${cur#@}
            kind='file'
        fi

        if [[ -n ${choices[$option]-} ]]; then
            readarray -t COMPREPLY < <(compgen -W "${choices[$option]}" -- "$cur")
            kind=""
        fi
    elif [[ -z $verb ]]; then
        readarray -t COMPREPLY < <(compgen -W "${verbs[*]}" -- "$cur")
    elif [[ $verb == completion && $position == 1 ]]; then
        readarray -t COMPREPLY < <(compgen -W "${shells[*]}" -- "$cur")
    elif [[ $verb != build && $verb != genkey && $verb != completion ]]; then
        kind='file'
    fi

    if [[ $kind == file || $kind == directory ]]; then
        compopt -o filenames
        readarray -t COMPREPLY < <(compgen -A "$kind" -- "$cur")
        if [[ -n ${COMPREPLY[0]-} && -z ${COMPREPLY[1]-} && -d ${COMPREPLY[0]} ]]; then
            compopt -o nospace
        fi
    fi

    for i in "${!COMPREPLY[@]}"; do
        word="${COMPREPLY[i]}"
        if [[ ( $kind == file || $kind == directory ) && -d $word ]]; then
            word+=/
        fi
        word="${prefix}${word}"
        COMPREPLY[i]=${word#"$wordbreak_prefix"}
    done
}

complete -F _ukify_completion ukify
