# tipc(8) completion                                       -*- shell-script -*-

_tipc_media() {
    local optind=$1

    if [[ $cword -eq $optind ]]; then
        COMPREPLY=( $( compgen -W 'media' -- $cur) )
        return 0
    elif [[ $cword -eq $optind+1 ]]; then
        COMPREPLY=( $( compgen -W 'udp eth ib' -- $cur) )
        return 0
    fi

    return 1
}

_tipc_bearer() {
    local optind=$1
    local media i

    if _tipc_media $optind; then
        return
    fi

    for ((i = 0; i < $cword; i++)); do
        if [[ ${words[$i]} == 'media' ]]; then
            media=${words[$(($i + 1))]}
        fi
    done

    if [[ $cword -eq $optind+2 ]]; then
        case "$media" in
        "udp")
            COMPREPLY=( $( compgen -W 'name' -- $cur) )
            ;;
        "eth" | "ib")
            COMPREPLY=( $( compgen -W 'device' -- $cur) )
            ;;
        esac
    elif [[ $cword -eq $optind+3 ]]; then
        case "$media" in
        "udp")
            local names=$(tipc bearer list 2>/dev/null | awk -F: '/^udp:/ {print $2}')
            COMPREPLY=( $( compgen -W '$names' -- $cur) )
            ;;
        "eth")
            local interfaces=$(command ls /sys/class/net/)
            COMPREPLY=( $( compgen -W '$interfaces' -- $cur ) )
            ;;
        esac
    fi
}

_tipc_link_opts() {
    COMPREPLY=( $( compgen -W 'priority tolerance window' -- $cur) )
}

_tipc_link() {
    local optind=$1
    local filter=$2

    if [[ $cword -eq $optind ]]; then
        COMPREPLY=( $( compgen -W 'link' -- $cur) )
    elif [[ $cword -eq $optind+1 ]]; then
        # awk drops link state and last trailing :
        local links=$(tipc link list 2>/dev/null | \
            awk '{print substr($1, 0, length($1))}')
        if [[ $filter == "peers" ]]; then
            links=$(command sed '/broadcast-link/d' <<<"$links")
        fi
        COMPREPLY=( $( compgen -W '$links' -- $cur ) )
    fi
}

_tipc()
{
    local cur prev words cword optind i p
    _init_completion || return

    optind=1
    COMPREPLY=()

    # Flags can be placed anywhere in the commandline
    case "$cur" in
        -*)
            COMPREPLY=( $( compgen -W '-h --help' -- $cur ) )
            return
            ;;
    esac

    if [[ $cword -eq 1 ]]; then
        COMPREPLY=( $( compgen -W 'bearer link media nametable node socket' -- $cur ) )
        return
    fi

    case "${words[$optind]}" in
    bearer)
        let optind++

        if [[ $cword -eq $optind ]]; then
            COMPREPLY=( $( compgen -W 'enable disable set get list' -- $cur ) )
            return
        fi

        case "${words[$optind]}" in
        enable)
            local media params
            let optind++

            if [[ $cword -lt $optind+4 ]]; then
                _tipc_bearer $optind
                return
            fi

            for ((i = 0; i < $cword; i++)); do
                if [[ ${words[$i]} == 'media' ]]; then
                    media=${words[$(($i + 1))]}
                fi
            done
            case "$media" in
                "udp")
                    declare -a  params=("localip" "localport" "remoteip"
                    "remoteport" "domain" "priority")
                    ;;
                "eth" | "ib")
                    declare -a params=("domain" "priority")
                    ;;
                *)
                    return
                    ;;
            esac

            # If the previous word was a known paramater we assume a value for
            # that key Note that this would break if the user attempts to use a
            # kown key as value
            for i in ${params[@]}; do
                if [[ $prev == $i ]]; then
                    return
                fi
            done

            # In order not to print already used options we remove them
            for p in ${words[@]}; do
                for i in ${params[@]}; do
                    if [[ $p == $i ]]; then
                        params=( "${params[@]/$i}" )
                    fi
                done
            done

            COMPREPLY=( $( compgen -W '${params[@]}' -- $cur) )
            ;;
        disable)
            let optind++

            _tipc_bearer $optind
            ;;
        get)
            let optind++

            if [[ $cword -eq $optind ]]; then
                _tipc_link_opts
            elif [[ $cword -ge $optind+1 ]]; then
                _tipc_bearer $(($optind + 1))
            fi
            ;;
        set)
            let optind++

            if [[ $cword -eq $optind ]]; then
                _tipc_link_opts
            elif [[ $cword -ge $optind+2 ]]; then
                _tipc_bearer $(($optind + 2))
            fi
            ;;
        esac
        ;;
    link)
        let optind++

        if [[ $cword -eq $optind ]]; then
            COMPREPLY=( $( compgen -W 'get set list statistics'  -- $cur ) )
            return
        fi

        case "${words[$optind]}" in
        get)
            let optind++

            if [[ $cword -eq $optind ]]; then
                _tipc_link_opts
            elif [[ $cword -ge $optind+1 ]]; then
                _tipc_link $(($optind + 1)) "peers"
            fi
            ;;
        set)
            let optind++

            if [[ $cword -eq $optind ]]; then
                _tipc_link_opts
            elif [[ $cword -ge $optind+2 ]]; then
                _tipc_link $(($optind + 2)) "peers"
            fi
            ;;
        statistics)
            let optind++

            if [[ $cword -eq $optind ]]; then
                COMPREPLY=( $( compgen -W 'show reset' -- $cur) )
                return
            fi

            case "${words[$optind]}" in
            show|reset)
                _tipc_link $(($optind + 1))
                ;;
            esac
            ;;
        esac
        ;;
    media)
        let optind++

        if [[ $cword -eq $optind ]]; then
            COMPREPLY=( $( compgen -W 'get set list'  -- $cur ) )
            return
        fi

        case "${words[$optind]}" in
        get)
            let optind++

            if [[ $cword -eq $optind ]]; then
                _tipc_link_opts
            elif [[ $cword -ge $optind+1 ]]; then
                _tipc_media $(($optind + 1))
            fi
            ;;
        set)
            let optind++

            if [[ $cword -eq $optind ]]; then
                _tipc_link_opts
            elif [[ $cword -ge $optind+2 ]]; then
                _tipc_media $(($optind + 2))
            fi
            ;;
        esac
        ;;
    nametable)
        let optind++

        if [[ $cword -eq $optind ]]; then
            COMPREPLY=( $( compgen -W 'show'  -- $cur ) )
        fi
        ;;
    node)
        let optind++

        if [[ $cword -eq $optind ]]; then
            COMPREPLY=( $( compgen -W 'list get set'  -- $cur ) )
            return
        fi

        case "${words[$optind]}" in
        get|set)
            let optind++

            if [[ $cword -eq $optind ]]; then
                COMPREPLY=( $( compgen -W 'address netid'  -- $cur ) )
            fi
        esac
        ;;
    socket)
        let optind++

        if [[ $cword -eq $optind ]]; then
            COMPREPLY=( $( compgen -W 'list'  -- $cur ) )
        fi
        ;;
    esac
} &&
complete -F _tipc tipc

# ex: filetype=sh
