#
# Copyright © 2018-2024 Inria.  All rights reserved.
# See COPYING in top-level directory.
#

# This file is also compatible with zsh (once bashcompinit is enabled)

# bash < 4 doesn't support compopt
[[ -z "$ZSH_VERSION" ]] && [[ "${BASH_VERSINFO[0]:-0}" -lt 4 ]] && return
# TODO only disable the nospace completion of "--filter"


_lstopo() {
    local INPUT_FORMAT=(xml synthetic fsroot cpuid)
    local OUTPUT_FORMAT=(default window console ascii tikz tex fig pdf nativesvg cairosvg ps png svg xml shmem synthetic)
    local TYPES=("Machine" "Misc" "Group" "NUMANode" "MemCache" "Package" "Die" "L1" "L2" "L3" "L4" "L5" "L1i" "L2i" "L3i" "Core" "Bridge" "PCIDev" "OSDev" "PU")
    local FILTERKINDS=("none" "all" "structure" "important")
    local OPTIONS=(-l --logical
		   -p --physical
                   --logical-index-prefix
                   --os-index-prefix
                   --output-format --of
		   -f --force
		   --only
		   -v --verbose
		   -q --quiet -s --silent
		   --distances
		   --distances-transform
		   --memattrs
		   --cpukinds
		   --windows-processor-groups
		   -c --cpuset
		   -C --cpuset-only
		   --cpuset-output-format --cof
		   --filter --ignore
		   --no-caches
		   --no-useless-caches
		   --no-icaches
		   --merge
		   --no-collapse
		   --factorize --factorize=
		   --no-factorize --no-factorize=
		   --restrict
		   --restrict-flags
		   --no-io
		   --no-bridges
		   --whole-io
		   --input -i
		   --input-format --if
		   --no-smt
		   --thissystem
		   --pid
		   --disallowed --whole-system
		   --allow
		   --flags
		   --children-order
		   --no-cpukinds
		   --fontsize
		   --gridsize
		   --linespacing
		   --thickness
		   --horiz --horiz=
		   --vert --vert=
		   --rect --rect=
		   --text --text=
		   --no-text --no-text=
		   --index --index=
		   --no-index --no-index=
		   --attrs --attrs=
		   --no-attrs --no-attrs=
		   --no-legend
		   --no-default-legend
		   --append-legend
		   --grey --greyscale
		   --palette
		   --binding-color
		   --disallowed-color
		   --top-color
		   --export-xml-flags
		   --export-synthetic-flags
		   --ps --top
		   --misc-from
		   --version
		   -h --help
		  )
    local cur=${COMP_WORDS[COMP_CWORD]}
    local prev=${COMP_WORDS[COMP_CWORD-1]}
    COMPREPLY=()

    if [[ $COMP_CWORD == 1 || $cur == -* ]] ; then
	COMPREPLY=( `compgen -W "${OPTIONS[*]}" -- "$cur"` )
    elif [[ $COMP_CWORD -ge 3 && "${COMP_WORDS[COMP_CWORD-2]}" == "--filter" && "$cur" == ":" ]] ; then
	COMPREPLY=( `compgen -W "${FILTERKINDS[*]}"` )
    elif [[ $COMP_CWORD -ge 4 && "${COMP_WORDS[COMP_CWORD-3]}" == "--filter" && "$prev" == ":" ]] ; then
	COMPREPLY=( `compgen -W "${FILTERKINDS[*]}" -- "$cur"` )
    elif [[ "$cur" == "=" && " --horiz --vert --rect --text --no-text --index --no-index --attrs --no-attrs --no-factorize " =~ " $prev " ]] ; then
	COMPREPLY=( `compgen -W "${TYPES[*]}"` )
	# we could also support "<type1>,<type2>,..." for --index/attrs/text but "," is not a completion word separator
    elif [[ $COMP_CWORD -ge 3 && "$prev" == "=" && " --horiz --vert --rect --text --no-text --index --no-index --attrs --no-attrs --no-factorize --factorize " =~ " ${COMP_WORDS[COMP_CWORD-2]} " ]] ; then
	COMPREPLY=( `compgen -W "${TYPES[*]}" -- "$cur"` )
    elif [[ "$cur" == "=" && "--factorize" = "$prev" ]] ; then
	COMPREPLY=( `compgen -W "${TYPES[*]}"` "<N>" "<N,F,L>" )
    else
	case "$prev" in
	    --of | --output-format)
		COMPREPLY=( `compgen -W "${OUTPUT_FORMAT[*]}" -- "$cur"` )
		;;
	    --only | --ignore)
		COMPREPLY=( `compgen -W "${TYPES[*]}" -- "$cur"` )
		;;
	    --filter)
		COMPREPLY=( `compgen -W "${TYPES[*]/%/:} cache: icache: io:" -- "$cur"` ) && compopt -o nospace
		;;
	    --restrict)
		COMPREPLY=( `compgen -W "binding <cpuset>" -- "$cur"` )
		;;
            --logical-index-prefix | --os-index-prefix)
	        COMPREPLY=( "<string>" "" )
		;;
	    -i | --input)
		_filedir xml
		;;
	    --if | --input-format)
		COMPREPLY=( `compgen -W "${INPUT_FORMAT[*]}" -- "$cur"` )
		;;
	    --pid)
		COMPREPLY=( "<pid>" "" )
		;;
	    --allow)
		COMPREPLY=( `compgen -W "all local <mask> nodeset=<mask>" -- "$cur"` )
		;;
	    --restrict-flags | --export-xml-flags | --export-synthetic-flags | --fontsize | --gridsize | --linespacing | --thickness)
		COMPREPLY=( "<integer>" "" )
		;;
	    --append-legend)
		COMPREPLY=( "<line of text>" "" )
		;;
	    --palette)
		COMPREPLY=( `compgen -W "grey greyscale default colors white none" -- "$cur"` )
		;;
	    --binding-color | --disallowed-color | --top-color)
		COMPREPLY=( `compgen -W "none <#rrggbb>" -- "$cur"` )
		;;
	    --children-order)
		COMPREPLY=( `compgen -W "plain memoryabove" -- "$cur"` )
		;;
	    --distances-transform)
	        COMPREPLY=( `compgen -W "links merge-switch-ports transitive-closure" -- "$cur"` )
		;;
	    --cpuset-output-format | --cof)
	        COMPREPLY=( "hwloc" "list" "taskset" )
		;;
	esac
    fi
}
complete -F _lstopo lstopo
complete -F _lstopo lstopo-no-graphics
complete -F _lstopo hwloc-ls


_hwloc_info(){
    local INPUT_FORMAT=(xml synthetic fsroot cpuid)
    local TYPES=("Machine" "Misc" "Group" "NUMANode" "MemCache" "Package" "Die" "L1" "L2" "L3" "L4" "L5" "L1i" "L2i" "L3i" "Core" "Bridge" "PCIDev" "OSDev" "PU")
    local FILTERKINDS=("none" "all" "structure" "important")
    local OPTIONS=(--objects
		   --topology
		   --support
		   -v --verbose
		   -q --quiet -s --silent
		   --get-attr
		   --ancestors
		   --ancestor
		   --children
		   --descendants
		   --local-memory
		   --local-memory-flags
		   --best-memattr
		   --first
		   -n
		   --restrict
		   --restrict-flags
		   --filter
		   --no-icaches
		   --no-io
		   --no-bridges
		   --whole-io
		   --input -i
		   --input-format --if
		   --thissystem
		   --pid
		   --disallowed --whole-system
		   -l --logical
		   -p --physical
		   --version
		   -h --help
		  )
    local cur=${COMP_WORDS[COMP_CWORD]}
    local prev=${COMP_WORDS[COMP_CWORD-1]}
    COMPREPLY=()

    if [[ $COMP_CWORD == 1 || $cur == -* ]] ; then
	COMPREPLY=( `compgen -W "${OPTIONS[*]}" -- "$cur"` )
    elif [[ $COMP_CWORD -ge 3 && "${COMP_WORDS[COMP_CWORD-2]}" == "--filter" && "$cur" == ":" ]] ; then
	COMPREPLY=( `compgen -W "${FILTERKINDS[*]}"` )
    elif [[ $COMP_CWORD -ge 4 && "${COMP_WORDS[COMP_CWORD-3]}" == "--filter" && "$prev" == ":" ]] ; then
	COMPREPLY=( `compgen -W "${FILTERKINDS[*]}" -- "$cur"` )
    else
	case "$prev" in
	    --restrict)
		COMPREPLY=( `compgen -W "binding <cpuset>" -- "$cur"` )
		;;
	    --restrict-flags)
		COMPREPLY=( "<integer>" "" )
		;;
	    -i | --input)
		_filedir xml
		;;
	    --if | --input-format)
		COMPREPLY=( `compgen -W "${INPUT_FORMAT[*]}" -- "$cur"` )
		;;
	    --pid)
		COMPREPLY=( "<pid>" "" )
		;;
	    --filter)
		COMPREPLY=( `compgen -W "${TYPES[*]/%/:} cache: icache: io:" -- "$cur"` ) && compopt -o nospace
		;;
	    --ancestor | --descendants)
		COMPREPLY=( `compgen -W "${TYPES[*]} kind=normal kind=cpu kind=cache kind=memory kind=io kind=all" -- "$cur"` )
		# TODO "kind=<tab>" doesn't complete with kinds
		;;
	    --local-memory-flags)
		COMPREPLY=( "<flags>" "" )
		;;
	    --best-memattr)
		COMPREPLY=( "<memattr>" "" )
		;;
	    --get-attr)
		COMPREPLY=( "<name>" "" )
		;;
	esac
    fi
}
complete -F _hwloc_info hwloc-info


_hwloc_bind(){
    local OPTIONS=(--cpubind
		   --membind
		   --mempolicy
		   --best-memattr
		   --logical -l
		   --physical -p
		   --single
		   --strict
		   --get
		   -e --get-last-cpu-location
		   --nodeset
		   --pid
		   --tid
		   --cpuset-output-format --cof
		   --restrict
		   --restrict-flags
		   --disallowed --whole-system
		   --hbm
		   --no-hbm
		   --no-smt --no-smt=N
		   -f --force
		   -q --quiet
		   -v --verbose
		   --version
		   -h --help
		  )
    local cur=${COMP_WORDS[COMP_CWORD]}
    local prev=${COMP_WORDS[COMP_CWORD-1]}
    COMPREPLY=()

    if [[ $COMP_CWORD == 1 || $cur == -* ]] ; then
	COMPREPLY=( `compgen -W "${OPTIONS[*]}" -- "$cur"` )
    else
	case "$prev" in
	    --mempolicy)
		COMPREPLY=( `compgen -W "default firsttouch bind interleave nexttouch" -- "$cur"` )
		;;
	    --pid)
	        COMPREPLY=( "<pid>" "" )
		;;
	    --tid)
		COMPREPLY=( "<tid>" "" )
		;;
	    --restrict)
		COMPREPLY=( "<bitmask>" "" )
		;;
	    --restrict-flags)
		COMPREPLY=( "<integer>" "" )
		;;
	    --best-memattr)
		COMPREPLY=( "<memattr>" "" )
		;;
	    --cpuset-output-format | --cof)
	        COMPREPLY=( "hwloc" "list" "taskset" )
		;;
	esac
    fi
}
complete -F _hwloc_bind hwloc-bind


_hwloc_calc(){
    local INPUT_FORMAT=(xml synthetic fsroot cpuid)
    local TYPES=("Machine" "Misc" "Group" "NUMANode" "MemCache" "Package" "Die" "L1" "L2" "L3" "L4" "L5" "L1i" "L2i" "L3i" "Core" "Bridge" "PCIDev" "OSDev" "PU")
    local OPTIONS=(-N --number-of
		   -I --intersect
		   -H --hierarchical
		   --largest
		   --local-memory
		   --local-memory-flags
		   --best-memattr
		   -l --logical
		   -p --physical
		   --li --logical-input
		   --lo --logical-output
		   --pi --physical-input
		   --po --physical-output
		   -n --nodeset
		   --ni --nodeset-input
		   --no --nodeset-output
                   --oo --object-output
		   --sep
		   --cpuset-input-format --cif --cpuset-output-format --cof
		   --single
		   --restrict
		   --restrict-flags
		   --disallowed --whole-system
		   --cpukind
		   --input -i
		   --input-format --if
		   --no-smt --no-smt=N
		   -q --quiet
		   -v --verbose
		   --version
		   -h --help
		  )
    local cur=${COMP_WORDS[COMP_CWORD]}
    local prev=${COMP_WORDS[COMP_CWORD-1]}
    COMPREPLY=()

    if [[ $COMP_CWORD == 1 || $cur == -* ]] ; then
	COMPREPLY=( `compgen -W "${OPTIONS[*]}" -- "$cur"` )
    else
	case "$prev" in
	    -N | --number-of | -I | --intersect)
		COMPREPLY=( `compgen -W "${TYPES[*]}" -- "$cur"` )
		;;
	    -H | --hierarchical)
		COMPREPLY=( "<type1>.<type2>..." "" )
		;;
	    --sep)
		COMPREPLY=( "<separator>" "" )
		;;
	    -i | --input)
		_filedir xml
		;;
	    --if | --input-format)
		COMPREPLY=( `compgen -W "${INPUT_FORMAT[*]}" -- "$cur"` )
		;;
	    --restrict)
		COMPREPLY=( "<bitmask>" "" )
		;;
	    --restrict-flags)
		COMPREPLY=( "<integer>" "" )
		;;
	    --local-memory-flags)
		COMPREPLY=( "<flags>" "" )
		;;
	    --best-memattr)
		COMPREPLY=( "<memattr>" "" )
		;;
	    --cpukind)
		COMPREPLY=( "<name>=<value>" "<n>" "" )
		;;
	    --cpuset-input-format | --cif | --cpuset-output-format | --cof)
	        COMPREPLY=( "hwloc" "list" "taskset" )
		;;
	esac
    fi
}
complete -F _hwloc_calc hwloc-calc


_hwloc_annotate(){
    local OPTIONS=(--ci --ri --cu --cd --version -h --help)
    local cur=${COMP_WORDS[COMP_CWORD]}
    COMPREPLY=()

    if [[ $COMP_CWORD == 1 || $cur == -* ]] ; then
	COMPREPLY=( `compgen -W "${OPTIONS[*]}" -- "$cur"`)
    fi
    _filedir xml
}
complete -F _hwloc_annotate hwloc-annotate


_hwloc_diff(){
    local OPTIONS=(--refname
		   --version
		   -h --help
		  )
    local cur=${COMP_WORDS[COMP_CWORD]}
    local prev=${COMP_WORDS[COMP_CWORD-1]}
    COMPREPLY=()

    if [[ $COMP_CWORD == 1 || $cur == -* ]] ; then
	COMPREPLY=( `compgen -W "${OPTIONS[*]}" -- "$cur"` )
    else
	case "$prev" in
	    --refname)
		COMPREPLY=( "<reference topology identifier>" "")
		return
		;;
	esac
    fi
    _filedir xml
}
complete -F _hwloc_diff hwloc-diff


_hwloc_patch(){
    local OPTIONS=(-R --reverse
		   --version
		   -h --help
		  )
    local cur=${COMP_WORDS[COMP_CWORD]}
    COMPREPLY=()

    if [[ $COMP_CWORD == 1 || $cur == -* ]] ; then
	COMPREPLY=( `compgen -W "${OPTIONS[*]}" -- "$cur"` )
    fi
    _filedir xml
}
complete -F _hwloc_patch hwloc-patch


_hwloc_compress_dir(){
    local OPTIONS=(-R --reverse
		   -v --verbose
		   --version
		   -h --help
		  )
    local cur=${COMP_WORDS[COMP_CWORD]}
    COMPREPLY=()

    if [[ $COMP_CWORD == 1 || $cur == -* ]] ; then
	COMPREPLY=( `compgen -W "${OPTIONS[*]}" -- "$cur"` )
    fi
    _filedir -d
}
complete -F _hwloc_compress_dir hwloc-compress-dir


_hwloc_distrib(){
    local INPUT_FORMAT=(xml synthetic fsroot cpuid)
    local TYPES=("Machine" "Misc" "Group" "NUMANode" "MemCache" "Package" "Die" "L1" "L2" "L3" "L4" "L5" "L1i" "L2i" "L3i" "Core" "Bridge" "PCIDev" "OSDev" "PU")
    local OPTIONS=(--ignore
		   --from
		   --to
		   --at
		   --reverse
		   --restrict
		   --restrict-flags
		   --disallowed --whole-system
		   --input -i
		   --input-format --if
		   --single
		   --cpuset-output-format --cof
		   -v --verbose
		   --version
		   -h --help
		  )
    local cur=${COMP_WORDS[COMP_CWORD]}
    local prev=${COMP_WORDS[COMP_CWORD-1]}
    COMPREPLY=()

    if [[ $COMP_CWORD == 1 || $cur == -* ]] ; then
	COMPREPLY=( `compgen -W "${OPTIONS[*]}" -- "$cur"` )
    else
	case "$prev" in
	    --ignore | --from | --to | --at)
		COMPREPLY=( `compgen -W "${TYPES[*]}" -- "$cur"` )
		;;
	    -i | --input)
		_filedir xml
		;;
	    --if | --input-format)
		COMPREPLY=( `compgen -W "${INPUT_FORMAT[*]}" -- "$cur"` )
		;;
	    --restrict)
		COMPREPLY=( "<bitmask>" "" )
		;;
	    --restrict-flags)
		COMPREPLY=( "<integer>" "" )
		;;
	    --cpuset-output-format | --cof)
	        COMPREPLY=( "hwloc" "list" "taskset" )
		;;
	esac
    fi
}
complete -F _hwloc_distrib hwloc-distrib


_hwloc_ps(){
    local OPTIONS=(-a
		   --pid
		   --children-of-pid
		   --name
		   --uid
		   -l --logical
		   -p --physical
		   -c --cpuset
		   --single-ancestor
		   -t --threads
		   -e --get-last-cpu-location
		   --pid-cmd
		   --short-name
		   --disallowed --whole-system
		   --lstopo-misc
		   --json-server
		   --json-port
		   -v --verbose
		   --version
		   -h --help
		  )
    local cur=${COMP_WORDS[COMP_CWORD]}
    local prev=${COMP_WORDS[COMP_CWORD-1]}
    COMPREPLY=()

    if [[ $COMP_CWORD == 1 || $cur == -* ]] ; then
	COMPREPLY=( `compgen -W "${OPTIONS[*]}" -- "$cur"` )
    else
	case "$prev" in
	--name)
	    COMPREPLY=( "<task name>" "" )
	    ;;
	--uid)
	    COMPREPLY=( "<uid>" "all" "" )
	    ;;
	--pid|--children-of-pid)
	    COMPREPLY=( "<pid>" "" )
	    ;;
	--pid-cmd)
	    _filedir
	    ;;
	--json-port)
	    COMPREPLY=( "<port>" "" )
	    ;;
	esac
    fi
}
complete -F _hwloc_ps hwloc-ps


_hwloc_gather_cpuid(){
    local OPTIONS=(-c
		   -q --quiet -s --silent
		   --version
		   -h --help
		   )
    local cur=${COMP_WORDS[COMP_CWORD]}
    local prev=${COMP_WORDS[COMP_CWORD-1]}
    COMPREPLY=()

    if [[ $COMP_CWORD == 1 || $cur == -* ]] ; then
	COMPREPLY=( `compgen -W "${OPTIONS[*]}" -- "$cur"` )
    else
	case "$prev" in
	    -c)
	        COMPREPLY=( "<index of cpu to operate on>" "" )
		;;
	esac
    fi
}
complete -F _hwloc_gather_cpuid hwloc-gather-cpuid


_hwloc_gather_topology(){
    local OPTIONS=(--io
		   --dmi
		   --dt
		   --no-cpuid
		   --keep
		   --version
		   -h --help
		  )
    local cur=${COMP_WORDS[COMP_CWORD]}
    COMPREPLY=()

    if [[ $COMP_CWORD == 1 || $cur == -* ]] ; then
	COMPREPLY=( `compgen -W "${OPTIONS[*]}" -- "$cur"` )
    fi
}
complete -F _hwloc_gather_topology hwloc-gather-topology
