: ${PROG:=$(basename ${BASH_SOURCE})}

__podman_previous_extglob_setting=$(shopt -p extglob)
shopt -s extglob

__podman_q() {
	podman ${host:+-H "$host"} ${config:+--config "$config"} 2>/dev/null "$@"
}

# __podman_containers returns a list of containers. Additional options to
# `podman ps` may be specified in order to filter the list, e.g.
# `__podman_containers --filter status=running`
# By default, only names are returned.
# Set PODMAN_COMPLETION_SHOW_CONTAINER_IDS=yes to also complete IDs.
# An optional first option `--id|--name` may be used to limit the
# output to the IDs or names of matching items. This setting takes
# precedence over the environment setting.
__podman_containers() {
	local format
	if [ "$1" = "--id" ] ; then
		format='{{.ID}}'
		shift
	elif [ "$1" = "--name" ] ; then
		format='{{.Names}}'
		shift
	elif [ "${PODMAN_COMPLETION_SHOW_CONTAINER_IDS}" = yes ] ; then
		format='{{.ID}} {{.Names}}'
	else
		format='{{.Names}}'
	fi
	__podman_q ps --format "$format" "$@"
}

# __podman_complete_containers applies completion of containers based on the current
# value of `$cur` or the value of the optional first option `--cur`, if given.
# Additional filters may be appended, see `__podman_containers`.
__podman_complete_containers() {
	local current="$cur"
	if [ "$1" = "--cur" ] ; then
		current="$2"
		shift 2
	fi
	COMPREPLY=( $(compgen -W "$(__podman_containers "$@")" -- "$current") )
}

__podman_complete_containers_all() {
	__podman_complete_containers "$@" --all
}

__podman_complete_containers_running() {
	__podman_complete_containers "$@" --filter status=running
}

__podman_complete_containers_stopped() {
	__podman_complete_containers "$@" --filter status=exited
}

__podman_complete_containers_unpauseable() {
	__podman_complete_containers "$@" --filter status=paused
}

__podman_complete_container_names() {
	local containers=( $(__podman_q ps -aq --no-trunc) )
	local names=( $(__podman_q inspect --format '{{.Name}}' "${containers[@]}") )
	names=( "${names[@]#/}" ) # trim off the leading "/" from the container names
	COMPREPLY=( $(compgen -W "${names[*]}" -- "$cur") )
}

__podman_complete_container_ids() {
	local containers=( $(__podman_q ps -aq) )
	COMPREPLY=( $(compgen -W "${containers[*]}" -- "$cur") )
}

__podman_images() {
	local images_args=""

	case "$PODMAN_COMPLETION_SHOW_IMAGE_IDS" in
		all)
			images_args="--no-trunc -a"
			;;
		non-intermediate)
			images_args="--no-trunc"
			;;
	esac

	local repo_print_command
	if [ "${PODMAN_COMPLETION_SHOW_TAGS:-yes}" = "yes" ]; then
		repo_print_command='print $1; print $1":"$2'
	else
		repo_print_command='print $1'
	fi

	local awk_script
	case "$PODMAN_COMPLETION_SHOW_IMAGE_IDS" in
		all|non-intermediate)
			awk_script='NR>1 { print $3; if ($1 != "<none>") { '"$repo_print_command"' } }'
			;;
		none|*)
			awk_script='NR>1 && $1 != "<none>" { '"$repo_print_command"' }'
			;;
	esac

	__podman_q images $images_args | awk "$awk_script" | grep -v '<none>$'
}

__podman_complete_images() {
	COMPREPLY=( $(compgen -W "$(__podman_images)" -- "$cur") )
	__ltrim_colon_completions "$cur"
}

__podman_complete_image_repos() {
	local repos="$(__podman_q images | awk 'NR>1 && $1 != "<none>" { print $1 }')"
	COMPREPLY=( $(compgen -W "$repos" -- "$cur") )
}

__podman_complete_image_repos_and_tags() {
	local reposAndTags="$(__podman_q images | awk 'NR>1 && $1 != "<none>" { print $1; print $1":"$2 }')"
	COMPREPLY=( $(compgen -W "$reposAndTags" -- "$cur") )
	__ltrim_colon_completions "$cur"
}

# __podman_networks returns a list of all networks. Additional options to
# `podman network ls` may be specified in order to filter the list, e.g.
# `__podman_networks --filter type=custom`
# By default, only names are returned.
# Set PODMAN_COMPLETION_SHOW_NETWORK_IDS=yes to also complete IDs.
# An optional first option `--id|--name` may be used to limit the
# output to the IDs or names of matching items. This setting takes
# precedence over the environment setting.
__podman_networks() {
	local format
	if [ "$1" = "--id" ] ; then
		format='{{.ID}}'
		shift
	elif [ "$1" = "--name" ] ; then
		format='{{.Name}}'
		shift
	elif [ "${PODMAN_COMPLETION_SHOW_NETWORK_IDS}" = yes ] ; then
		format='{{.ID}} {{.Name}}'
	else
		format='{{.Name}}'
	fi
	__podman_q network ls --format "$format" "$@"
}

# __podman_complete_networks applies completion of networks based on the current
# value of `$cur` or the value of the optional first option `--cur`, if given.
# Additional filters may be appended, see `__podman_networks`.
__podman_complete_networks() {
	local current="$cur"
	if [ "$1" = "--cur" ] ; then
		current="$2"
		shift 2
	fi
	COMPREPLY=( $(compgen -W "$(__podman_networks "$@")" -- "$current") )
}

__podman_complete_containers_in_network() {
	local containers=$(__podman_q network inspect -f '{{range $i, $c := .Containers}}{{$i}} {{$c.Name}} {{end}}' "$1")
	COMPREPLY=( $(compgen -W "$containers" -- "$cur") )
}

__podman_runtimes() {
	__podman_q info | sed -n 's/^Runtimes: \(.*\)/\1/p'
}

__podman_complete_runtimes() {
	COMPREPLY=( $(compgen -W "$(__podman_runtimes)" -- "$cur") )
}

# __podman_services returns a list of all services. Additional options to
# `podman service ls` may be specified in order to filter the list, e.g.
# `__podman_services --filter name=xxx`
# By default, only node names are returned.
# Set PODMAN_COMPLETION_SHOW_SERVICE_IDS=yes to also complete IDs.
# An optional first option `--id|--name` may be used to limit the
# output to the IDs or names of matching items. This setting takes
# precedence over the environment setting.
__podman_services() {
	local fields='$2'  # default: service name only
	[ "${PODMAN_COMPLETION_SHOW_SERVICE_IDS}" = yes ] && fields='$1,$2' # ID & name

	if [ "$1" = "--id" ] ; then
		fields='$1' # IDs only
		shift
	elif [ "$1" = "--name" ] ; then
		fields='$2' # names only
		shift
	fi
        __podman_q service ls "$@" | awk "NR>1 {print $fields}"
}

# __podman_complete_services applies completion of services based on the current
# value of `$cur` or the value of the optional first option `--cur`, if given.
# Additional filters may be appended, see `__podman_services`.
__podman_complete_services() {
	local current="$cur"
	if [ "$1" = "--cur" ] ; then
		current="$2"
		shift 2
	fi
	COMPREPLY=( $(compgen -W "$(__podman_services "$@")" -- "$current") )
}

# __podman_append_to_completions appends the word passed as an argument to every
# word in `$COMPREPLY`.
# Normally you do this with `compgen -S` while generating the completions.
# This function allows you to append a suffix later. It allows you to use
# the __podman_complete_XXX functions in cases where you need a suffix.
__podman_append_to_completions() {
	COMPREPLY=( ${COMPREPLY[@]/%/"$1"} )
}

# __podman_pos_first_nonflag finds the position of the first word that is neither
# option nor an option's argument. If there are options that require arguments,
# you should pass a glob describing those options, e.g. "--option1|-o|--option2"
# Use this function to restrict completions to exact positions after the argument list.
__podman_pos_first_nonflag() {
	local argument_flags=$1

	local counter=$((${subcommand_pos:-${command_pos}} + 1))
	while [ $counter -le $cword ]; do
		if [ -n "$argument_flags" ] && eval "case '${words[$counter]}' in $argument_flags) true ;; *) false ;; esac"; then
			(( counter++ ))
			# eat "=" in case of --option=arg syntax
			[ "${words[$counter]}" = "=" ] && (( counter++ ))
		else
			case "${words[$counter]}" in
				-*)
					;;
				*)
					break
					;;
			esac
		fi

		# Bash splits words at "=", retaining "=" as a word, examples:
		# "--debug=false" => 3 words, "--log-opt syslog-facility=daemon" => 4 words
		while [ "${words[$counter + 1]}" = "=" ] ; do
			counter=$(( counter + 2))
		done

		(( counter++ ))
	done

	echo $counter
}

# __podman_map_key_of_current_option returns `key` if we are currently completing the
# value of a map option (`key=value`) which matches the extglob given as an argument.
# This function is needed for key-specific completions.
__podman_map_key_of_current_option() {
	local glob="$1"

	local key glob_pos
	if [ "$cur" = "=" ] ; then        # key= case
		key="$prev"
		glob_pos=$((cword - 2))
	elif [[ $cur == *=* ]] ; then     # key=value case (OSX)
		key=${cur%=*}
		glob_pos=$((cword - 1))
	elif [ "$prev" = "=" ] ; then
		key=${words[$cword - 2]}  # key=value case
		glob_pos=$((cword - 3))
	else
		return
	fi

	[ "${words[$glob_pos]}" = "=" ] && ((glob_pos--))  # --option=key=value syntax

	[[ ${words[$glob_pos]} == @($glob) ]] && echo "$key"
}

# __podman_value_of_option returns the value of the first option matching `option_glob`.
# Valid values for `option_glob` are option names like `--log-level` and globs like
# `--log-level|-l`
# Only positions between the command and the current word are considered.
__podman_value_of_option() {
	local option_extglob=$(__podman_to_extglob "$1")

	local counter=$((command_pos + 1))
	while [ $counter -lt $cword ]; do
		case ${words[$counter]} in
			$option_extglob )
				echo ${words[$counter + 1]}
				break
				;;
		esac
		(( counter++ ))
	done
}

# __podman_to_alternatives transforms a multiline list of strings into a single line
# string with the words separated by `|`.
# This is used to prepare arguments to __podman_pos_first_nonflag().
__podman_to_alternatives() {
	local parts=( $1 )
	local IFS='|'
	echo "${parts[*]}"
}

# __podman_to_extglob transforms a multiline list of options into an extglob pattern
# suitable for use in case statements.
__podman_to_extglob() {
	local extglob=$( __podman_to_alternatives "$1" )
	echo "@($extglob)"
}

# __podman_subcommands processes subcommands
# Locates the first occurrence of any of the subcommands contained in the
# first argument. In case of a match, calls the corresponding completion
# function and returns 0.
# If no match is found, 1 is returned. The calling function can then
# continue processing its completion.
#
# TODO if the preceding command has options that accept arguments and an
# argument is equal ot one of the subcommands, this is falsely detected as
# a match.
__podman_subcommands() {
	local subcommands="$1"

	local counter=$(($command_pos + 1))
	while [ $counter -lt $cword ]; do
		case "${words[$counter]}" in
			$(__podman_to_extglob "$subcommands") )
				subcommand_pos=$counter
				local subcommand=${words[$counter]}
				local completions_func=_podman_${command}_${subcommand}
				declare -F $completions_func >/dev/null && $completions_func
				return 0
				;;
		esac
		(( counter++ ))
	done
	return 1
}

# __podman_nospace suppresses trailing whitespace
__podman_nospace() {
	# compopt is not available in ancient bash versions
	type compopt &>/dev/null && compopt -o nospace
}

__podman_complete_resolved_hostname() {
	command -v host >/dev/null 2>&1 || return
	COMPREPLY=( $(host 2>/dev/null "${cur%:}" | awk '/has address/ {print $4}') )
}

__podman_local_interfaces() {
	command -v ip >/dev/null 2>&1 || return
	ip addr show scope global 2>/dev/null | sed -n 's| \+inet \([0-9.]\+\).* \([^ ]\+\)|\1 \2|p'
}

__podman_complete_local_interfaces() {
	local additional_interface
	if [ "$1" = "--add" ] ; then
		additional_interface="$2"
	fi

	COMPREPLY=( $( compgen -W "$(__podman_local_interfaces) $additional_interface" -- "$cur" ) )
}

__podman_complete_capabilities() {
	# The list of capabilities is defined in types.go, ALL was added manually.
	COMPREPLY=( $( compgen -W "
		ALL
		AUDIT_CONTROL
		AUDIT_WRITE
		AUDIT_READ
		BLOCK_SUSPEND
		CHOWN
		DAC_OVERRIDE
		DAC_READ_SEARCH
		FOWNER
		FSETID
		IPC_LOCK
		IPC_OWNER
		KILL
		LEASE
		LINUX_IMMUTABLE
		MAC_ADMIN
		MAC_OVERRIDE
		MKNOD
		NET_ADMIN
		NET_BIND_SERVICE
		NET_BROADCAST
		NET_RAW
		SETFCAP
		SETGID
		SETPCAP
		SETUID
		SYS_ADMIN
		SYS_BOOT
		SYS_CHROOT
		SYSLOG
		SYS_MODULE
		SYS_NICE
		SYS_PACCT
		SYS_PTRACE
		SYS_RAWIO
		SYS_RESOURCE
		SYS_TIME
		SYS_TTY_CONFIG
		WAKE_ALARM
	" -- "$cur" ) )
}

__podman_complete_detach-keys() {
	case "$prev" in
		--detach-keys)
			case "$cur" in
				*,)
					COMPREPLY=( $( compgen -W "${cur}ctrl-" -- "$cur" ) )
					;;
				*)
					COMPREPLY=( $( compgen -W "ctrl-" -- "$cur" ) )
					;;
			esac

			__podman_nospace
			return
			;;
	esac
	return 1
}

__podman_complete_log_drivers() {
	COMPREPLY=( $( compgen -W "
		awslogs
		etwlogs
		fluentd
		gcplogs
		gelf
		journald
		json-file
		logentries
		none
		splunk
		syslog
	" -- "$cur" ) )
}

__podman_complete_log_options() {
	# see docs/reference/logging/index.md
	local awslogs_options="awslogs-region awslogs-group awslogs-stream"
	local fluentd_options="env fluentd-address fluentd-async-connect fluentd-buffer-limit fluentd-retry-wait fluentd-max-retries labels tag"
	local gcplogs_options="env gcp-log-cmd gcp-project labels"
	local gelf_options="env gelf-address gelf-compression-level gelf-compression-type labels tag"
	local journald_options="env labels tag"
	local json_file_options="env labels max-file max-size"
	local logentries_options="logentries-token"
	local syslog_options="env labels syslog-address syslog-facility syslog-format syslog-tls-ca-cert syslog-tls-cert syslog-tls-key syslog-tls-skip-verify tag"
	local splunk_options="env labels splunk-caname splunk-capath splunk-format splunk-gzip splunk-gzip-level splunk-index splunk-insecureskipverify splunk-source splunk-sourcetype splunk-token splunk-url splunk-verify-connection tag"

	local all_options="$fluentd_options $gcplogs_options $gelf_options $journald_options $logentries_options $json_file_options $syslog_options $splunk_options"

	case $(__podman_value_of_option --log-driver) in
		'')
			COMPREPLY=( $( compgen -W "$all_options" -S = -- "$cur" ) )
			;;
		awslogs)
			COMPREPLY=( $( compgen -W "$awslogs_options" -S = -- "$cur" ) )
			;;
		fluentd)
			COMPREPLY=( $( compgen -W "$fluentd_options" -S = -- "$cur" ) )
			;;
		gcplogs)
			COMPREPLY=( $( compgen -W "$gcplogs_options" -S = -- "$cur" ) )
			;;
		gelf)
			COMPREPLY=( $( compgen -W "$gelf_options" -S = -- "$cur" ) )
			;;
		journald)
			COMPREPLY=( $( compgen -W "$journald_options" -S = -- "$cur" ) )
			;;
		json-file)
			COMPREPLY=( $( compgen -W "$json_file_options" -S = -- "$cur" ) )
			;;
		logentries)
			COMPREPLY=( $( compgen -W "$logentries_options" -S = -- "$cur" ) )
			;;
		syslog)
			COMPREPLY=( $( compgen -W "$syslog_options" -S = -- "$cur" ) )
			;;
		splunk)
			COMPREPLY=( $( compgen -W "$splunk_options" -S = -- "$cur" ) )
			;;
		*)
			return
			;;
	esac

	__podman_nospace
}

__podman_complete_log_driver_options() {
	local key=$(__podman_map_key_of_current_option '--log-opt')
	case "$key" in
		fluentd-async-connect)
			COMPREPLY=( $( compgen -W "false true" -- "${cur##*=}" ) )
			return
			;;
		gelf-address)
			COMPREPLY=( $( compgen -W "udp" -S "://" -- "${cur##*=}" ) )
			__podman_nospace
			return
			;;
		gelf-compression-level)
			COMPREPLY=( $( compgen -W "1 2 3 4 5 6 7 8 9" -- "${cur##*=}" ) )
			return
			;;
		gelf-compression-type)
			COMPREPLY=( $( compgen -W "gzip none zlib" -- "${cur##*=}" ) )
			return
			;;
		syslog-address)
			COMPREPLY=( $( compgen -W "tcp:// tcp+tls:// udp:// unix://" -- "${cur##*=}" ) )
			__podman_nospace
			__ltrim_colon_completions "${cur}"
			return
			;;
		syslog-facility)
			COMPREPLY=( $( compgen -W "
				auth
				authpriv
				cron
				daemon
				ftp
				kern
				local0
				local1
				local2
				local3
				local4
				local5
				local6
				local7
				lpr
				mail
				news
				syslog
				user
				uucp
			" -- "${cur##*=}" ) )
			return
			;;
		syslog-format)
			COMPREPLY=( $( compgen -W "rfc3164 rfc5424 rfc5424micro" -- "${cur##*=}" ) )
			return
			;;
		syslog-tls-ca-cert|syslog-tls-cert|syslog-tls-key)
			_filedir
			return
			;;
		syslog-tls-skip-verify)
			COMPREPLY=( $( compgen -W "true" -- "${cur##*=}" ) )
			return
			;;
		splunk-url)
			COMPREPLY=( $( compgen -W "http:// https://" -- "${cur##*=}" ) )
			__podman_nospace
			__ltrim_colon_completions "${cur}"
			return
			;;
		splunk-gzip|splunk-insecureskipverify|splunk-verify-connection)
			COMPREPLY=( $( compgen -W "false true" -- "${cur##*=}" ) )
			return
			;;
		splunk-format)
			COMPREPLY=( $( compgen -W "inline json raw" -- "${cur##*=}" ) )
			return
			;;
	esac
	return 1
}

__podman_complete_log_levels() {
	COMPREPLY=( $( compgen -W "debug info warn error fatal" -- "$cur" ) )
}

# __podman_complete_signals returns a subset of the available signals that is most likely
# relevant in the context of podman containers
__podman_complete_signals() {
	local signals=(
		SIGCONT
		SIGHUP
		SIGINT
		SIGKILL
		SIGQUIT
		SIGSTOP
		SIGTERM
		SIGUSR1
		SIGUSR2
	)
	COMPREPLY=( $( compgen -W "${signals[*]} ${signals[*]#SIG}" -- "$( echo $cur | tr '[:lower:]' '[:upper:]')" ) )
}

__podman_complete_user_group() {
	if [[ $cur == *:* ]] ; then
		COMPREPLY=( $(compgen -g -- "${cur#*:}") )
	else
		COMPREPLY=( $(compgen -u -S : -- "$cur") )
		__podman_nospace
	fi
}

__podman_list_images() {
    COMPREPLY=($(compgen -W "$(podman images -q)" -- $cur))
}

__podman_list_containers() {
    COMPREPLY=($(compgen -W "$(podman ps -aq)" -- $cur))
}

__podman_images() {
	local images_args=""

	case "$PODMAN_COMPLETION_SHOW_IMAGE_IDS" in
		all)
			images_args="--no-trunc -a"
			;;
		non-intermediate)
			images_args="--no-trunc"
			;;
	esac

	local repo_print_command
	if [ "${PODMAN_COMPLETION_SHOW_TAGS:-yes}" = "yes" ]; then
		repo_print_command='print $1; print $1":"$2'
	else
		repo_print_command='print $1'
	fi

	local awk_script
	case "$PODMAN_COMPLETION_SHOW_IMAGE_IDS" in
		all|non-intermediate)
			awk_script='NR>1 { print $3; if ($1 != "<none>") { '"$repo_print_command"' } }'
			;;
		none|*)
			awk_script='NR>1 && $1 != "<none>" { '"$repo_print_command"' }'
			;;
	esac

	__podman_q images $images_args | awk "$awk_script" | grep -v '<none>$'
}

_podman_attach() {
     local options_with_args="
     --detach-keys
     "
     local boolean_options="
     --help
     -h
     --latest
     -l
     --no-stdin
     --sig-proxy
     "
     _complete_ "$options_with_args" "$boolean_options"
}

_podman_commit() {
    local options_with_args="
	--author
	-a
	--change
	-c
	--message
	-m
     "
    local boolean_options="
	--help
	-h
	--pause
	-p
	--quiet
	-q
     "
    _complete_ "$options_with_args" "$boolean_options"

    case "$cur" in
        -*)
            COMPREPLY=($(compgen -W "$boolean_options $options_with_args" -- "$cur"))
            ;;
        *)
            __podman_list_images
            ;;
    esac
}

_podman_build() {
     local boolean_options="
     --build
     --help
     -h
     --pull
     --pull-always
     --quiet
     -q
     --tls-verify
  "

     local options_with_args="
     --authfile
     --build-arg
     --cert-dir
     --creds
     --file
     -f
     --format
     --runtime
     --runtime-flag
     --signature-policy
     --tag
     -t
  "

     local all_options="$options_with_args $boolean_options"

     case "$prev" in
         --runtime)
             COMPREPLY=($(compgen -W 'runc runv' -- "$cur"))
             ;;
         $(__buildah_to_extglob "$options_with_args"))
 return
 ;;
 esac

 case "$cur" in
     -*)
         COMPREPLY=($(compgen -W "$boolean_options $options_with_args" -- "$cur"))
         ;;
 esac
}

_podman_diff() {
    local options_with_args="
     --format
     "
    local boolean_options="
     "
    _complete_ "$options_with_args" "$boolean_options"

    case "$cur" in
        -*)
            COMPREPLY=($(compgen -W "$boolean_options $options_with_args" -- "$cur"))
            ;;
        *)
            __podman_list_images
            ;;
    esac
}

_podman_exec() {
    local options_with_args="
    -e
    --env
    --user
    -u
     "
    local boolean_options="
    --latest
    -l
    --privileged
    --tty
    -t
     "
    _complete_ "$options_with_args" "$boolean_options"

}
_podman_export() {
    local options_with_args="
     --output
     -o
     "
    local boolean_options="
     "
    _complete_ "$options_with_args" "$boolean_options"

    case "$cur" in
        -*)
            COMPREPLY=($(compgen -W "$boolean_options $options_with_args" -- "$cur"))
            ;;
        *)
            __podman_list_images
            ;;
    esac
}

_podman_history() {
    local options_with_args="
     --format
     "
    local boolean_options="
     --human -H
     --no-trunc
     --quiet -q
     "
    _complete_ "$options_with_args" "$boolean_options"

    case "$cur" in
        -*)
            COMPREPLY=($(compgen -W "$boolean_options $options_with_args" -- "$cur"))
            ;;
        *)
            __podman_list_images
            ;;
    esac
}


_podman_import() {
    local options_with_args="
	--change
	-c
	--message
	-m
     "
    local boolean_options="
	--help
	-h
	--quiet
	-q
     "
    _complete_ "$options_with_args" "$boolean_options"

    case "$cur" in
        -*)
            COMPREPLY=($(compgen -W "$boolean_options $options_with_args" -- "$cur"))
            ;;
        *)
            __podman_list_images
            ;;
    esac
}

_podman_info() {
    local boolean_options="
     --help
     -h
     --debug
     "
    local options_with_args="
    --format
  "

    local all_options="$options_with_args $boolean_options"

    case "$cur" in
        -*)
            COMPREPLY=($(compgen -W "$boolean_options $options_with_args" -- "$cur"))
            ;;
        *)
            __podman_list_images
            ;;
    esac
}

_podman_images() {
    local boolean_options="
     --help
     -h
     --quiet
     -q
     --noheading
     -n
     --no-trunc
     --digests
     --filter
     -f
     "
    local options_with_args="
    --format
  "

    local all_options="$options_with_args $boolean_options"

    case "$cur" in
        -*)
            COMPREPLY=($(compgen -W "$boolean_options $options_with_args" -- "$cur"))
            ;;
    esac
}

_podman_inspect() {
    local boolean_options="
     --help
     -h
     --latest
     -l
     "
    local options_with_args="
    --format
     -f
     --type
     -t
     --size
  "

    local all_options="$options_with_args $boolean_options"

    case "$cur" in
        -*)
            COMPREPLY=($(compgen -W "$boolean_options $options_with_args" -- "$cur"))
            ;;
    esac
}
_podman_kill() {
     local options_with_args="
     --signal -s
     "
     local boolean_options="
     --help
     -h
     --latest
     -l
     "
     _complete_ "$options_with_args" "$boolean_options"
}

_podman_logs() {
     local options_with_args="
     --since
     --tail
     "
     local boolean_options="
     --follow
     -f
     --latest
     -l
     --timestamps
     -t
     "
     _complete_ "$options_with_args" "$boolean_options"

    case "$cur" in
        -*)
            COMPREPLY=($(compgen -W "$boolean_options $options_with_args" -- "$cur"))
            ;;
        *)
            __podman_list_containers
            ;;
    esac
}

_podman_pull() {
    local options_with_args="
    --authfile
    --creds
    --cert-dir
    --signature-policy
    "
    local boolean_options="
    --all-tags -a
    --quiet
    -q
    --tls-verify
    "
    _complete_ "$options_with_args" "$boolean_options"
}

_podman_search() {
	local options_with_args="
	--filter -f
	--format
	--limit
	--registry
	"
	local boolean_options="
	--no-trunc
	"
	_complete_ "$options_with_args" "$boolean_options"
}

_podman_unmount() {
    _podman_umount $@
}

_podman_umount() {
    local boolean_options="
    --help
    -h
 "
    local options_with_args="
 "

    local all_options="$options_with_args $boolean_options"

    case "$cur" in
        -*)
            COMPREPLY=($(compgen -W "$boolean_options $options_with_args" -- "$cur"))
            ;;
    esac
}

_podman_mount() {
    local boolean_options="
    --help
    -h
    --notruncate
 "

    local options_with_args="
    --format
 "

    local all_options="$options_with_args $boolean_options"

    case "$cur" in
        -*)
            COMPREPLY=($(compgen -W "$boolean_options $options_with_args" -- "$cur"))
            ;;
    esac
}

_podman_push() {
    local boolean_options="
    --compress
    --quiet
    -q
    --remove-signatures
    --tls-verify
  "

    local options_with_args="
    --authfile
	--format
    --cert-dir
    --creds
    --sign-by
    --signature-policy
  "

    local all_options="$options_with_args $boolean_options"

    case "$cur" in
        -*)
            COMPREPLY=($(compgen -W "$boolean_options $options_with_args" -- "$cur"))
            ;;
    esac
}

_podman_container_run() {
	local options_with_args="
		--add-host
		--attach -a
		--blkio-weight
		--blkio-weight-device
		--builtin-volume
		--cap-add
		--cap-drop
		--cgroup-parent
		--cidfile
		--cpu-period
		--cpu-quota
		--cpu-rt-period
		--cpu-rt-runtime
		--cpuset-cpus
		--cpus
		--cpuset-mems
		--cpu-shares -c
		--device
		--device-read-bps
		--device-read-iops
		--device-write-bps
		--device-write-iops
		--dns
		--dns-option
		--dns-search
		--entrypoint
		--env -e
		--env-file
		--expose
		--group-add
		--hostname -h
		--image-volume
		--init-path
		--ip
		--ip6
		--ipc
		--kernel-memory
		--label-file
		--label -l
		--link-local-ip
		--log-driver
		--log-opt
		--mac-address
		--memory -m
		--memory-swap
		--memory-swappiness
		--memory-reservation
		--name
		--network
		--network-alias
		--oom-score-adj
		--pid
		--pids-limit
		--publish -p
		--runtime
		--security-opt
		--shm-size
		--stop-signal
		--stop-timeout
		--tmpfs
		--sysctl
		--ulimit
		--user -u
		--userns
		--uts
		--volumes-from
		--volume -v
		--workdir -w
	"

	local boolean_options="
		--disable-content-trust=false
		--help
		--init
		--interactive -i
		--oom-kill-disable
		--privileged
		--publish-all -P
		--quiet
		--read-only
		--tty -t
	"

	if [ "$command" = "run" -o "$subcommand" = "run" ] ; then
		options_with_args="$options_with_args
			--detach-keys
			--health-cmd
			--health-interval
			--health-retries
			--health-timeout
		"
		boolean_options="$boolean_options
			--detach -d
			--no-healthcheck
			--rm
			--sig-proxy=false
		"
		__podman_complete_detach-keys && return
	fi

	local all_options="$options_with_args $boolean_options"


	__podman_complete_log_driver_options && return

	local key=$(__podman_map_key_of_current_option '--security-opt')
	case "$key" in
		label)
			[[ $cur == *: ]] && return
			COMPREPLY=( $( compgen -W "user: role: type: level: disable" -- "${cur##*=}") )
			if [ "${COMPREPLY[*]}" != "disable" ] ; then
				__podman_nospace
			fi
			return
			;;
		seccomp)
			local cur=${cur##*=}
			_filedir
			COMPREPLY+=( $( compgen -W "unconfined" -- "$cur" ) )
			return
			;;
	esac

	case "$prev" in
		--add-host)
			case "$cur" in
				*:)
					__podman_complete_resolved_hostname
					return
					;;
			esac
			;;
		--attach|-a)
			COMPREPLY=( $( compgen -W 'stdin stdout stderr' -- "$cur" ) )
			return
			;;
		--cap-add|--cap-drop)
			__podman_complete_capabilities
			return
			;;
		--cidfile|--env-file|--init-path|--label-file)
			_filedir
			return
			;;
		--device|--tmpfs|--volume|-v)
			case "$cur" in
				*:*)
					# TODO somehow do _filedir for stuff inside the image, if it's already specified (which is also somewhat difficult to determine)
					;;
				'')
					COMPREPLY=( $( compgen -W '/' -- "$cur" ) )
					__podman_nospace
					;;
				/*)
					_filedir
					__podman_nospace
					;;
			esac
			return
			;;
		--env|-e)
			# we do not append a "=" here because "-e VARNAME" is legal systax, too
			COMPREPLY=( $( compgen -e -- "$cur" ) )
			__podman_nospace
			return
			;;
		--ipc)
			case "$cur" in
				*:*)
					cur="${cur#*:}"
					__podman_complete_containers_running
					;;
				*)
					COMPREPLY=( $( compgen -W 'host container:' -- "$cur" ) )
					if [ "$COMPREPLY" = "container:" ]; then
						__podman_nospace
					fi
					;;
			esac
			return
			;;
		--log-driver)
			__podman_complete_log_drivers
			return
			;;
		--log-opt)
			__podman_complete_log_options
			return
			;;
		--network)
			case "$cur" in
				container:*)
					__podman_complete_containers_all --cur "${cur#*:}"
					;;
				*)
					COMPREPLY=( $( compgen -W "$(__podman_plugins_bundled --type Network) $(__podman_networks) container:" -- "$cur") )
					if [ "${COMPREPLY[*]}" = "container:" ] ; then
						__podman_nospace
					fi
					;;
			esac
			return
			;;
		--pid)
			case "$cur" in
				*:*)
					__podman_complete_containers_running --cur "${cur#*:}"
					;;
				*)
					COMPREPLY=( $( compgen -W 'host container:' -- "$cur" ) )
					if [ "$COMPREPLY" = "container:" ]; then
						__podman_nospace
					fi
					;;
			esac
			return
			;;
		--runtime)
			__podman_complete_runtimes
			return
			;;
		--security-opt)
			COMPREPLY=( $( compgen -W "apparmor= label= no-new-privileges seccomp=" -- "$cur") )
			if [ "${COMPREPLY[*]}" != "no-new-privileges" ] ; then
				__podman_nospace
			fi
			return
			;;
		--storage-opt)
			COMPREPLY=( $( compgen -W "size" -S = -- "$cur") )
			__podman_nospace
			return
			;;
		--user|-u)
			__podman_complete_user_group
			return
			;;
		--userns)
			COMPREPLY=( $( compgen -W "host" -- "$cur" ) )
			return
			;;
		--volumes-from)
			__podman_complete_containers_all
			return
			;;
		$(__podman_to_extglob "$options_with_args") )
			return
			;;
	esac

	case "$cur" in
		-*)
			COMPREPLY=( $( compgen -W "$all_options" -- "$cur" ) )
			;;
		*)
			local counter=$( __podman_pos_first_nonflag $( __podman_to_alternatives "$options_with_args" ) )
			if [ $cword -eq $counter ]; then
				__podman_complete_images
			fi
			;;
	esac
}

_podman_create() {
	_podman_container_run
}

_podman_run() {
	_podman_container_run
}

_podman_restart() {
     local options_with_args="
     --timeout -t
     "
     local boolean_options="
     --latest
     -l"
     _complete_ "$options_with_args" "$boolean_options"
}

_podman_rm() {
    local boolean_options="
    --all
    -a
    --force
    -f
    --latest
    -l
    "

    local options_with_args="
    "

    local all_options="$options_with_args $boolean_options"

    case "$cur" in
        -*)
            COMPREPLY=($(compgen -W "$boolean_options $options_with_args" -- "$cur"))
            ;;
        *)
            __podman_list_containers
            ;;
    esac
}

_podman_rmi() {
    local boolean_options="
     --help
     -h
     --force
     -f
     -a
     --all
  "

    case "$cur" in
        -*)
            COMPREPLY=($(compgen -W "$boolean_options $options_with_args" -- "$cur"))
            ;;
        *)
            __podman_list_images
            ;;
    esac
}

_podman_stats() {
    local boolean_options="
     --help
     --all
     -a
     --no-stream
     --format
     --no-reset
    "

    case "$cur" in
        -*)
            COMPREPLY=($(compgen -W "$boolean_options $options_with_args" -- "$cur"))
            ;;
        *)
            __podman_list_containers
            ;;
    esac
}

podman_tag() {
    local options_with_args="
    "
    local boolean_options="
    "
    _complete_ "$options_with_args" "$boolean_options"
}

podman_top() {
    local options_with_args="
    "
    local boolean_options="
    --help
    -h
    --latest
    -l
    "
    _complete_ "$options_with_args" "$boolean_options"
}

_podman_version() {
     local options_with_args="
     "
     local boolean_options="
     "
     _complete_ "$options_with_args" "$boolean_options"
}

_podman_save() {
     local options_with_args="
     --output -o
     --format
     "
     local boolean_options="
	 --compress
	 -q
	 --quiet
     "
     _complete_ "$options_with_args" "$boolean_options"
}

_podman_export() {
     local options_with_args="
     --output -o
     "
     local boolean_options="
     "
     _complete_ "$options_with_args" "$boolean_options"
}

_podman_pause() {
     local options_with_args="
     --help -h
     "
     local boolean_options=""
     _complete_ "$options_with_args" "$boolean_options"
}

_podman_port() {
     local options_with_args="
     --help -h
     "
     local boolean_options="
     --all
     -a
     -l
     --latest"
     _complete_ "$options_with_args" "$boolean_options"
}

_podman_ps() {
     local options_with_args="
     --filter -f
     --format
     --last -n
     "
     local boolean_options="
     --all -a
     --latest -l
     --no-trunc
     --quiet -q
     --size -s
     --namespace --ns
     "
     _complete_ "$options_with_args" "$boolean_options"
}

_podman_start() {
     local options_with_args="
     --detach-keys
     "

     local boolean_options="
     -h
     --help
     -a
     --attach
     -i
     --interactive
     --latest
     -l
     --sig-proxy
     "
     _complete_ "$options_with_args" "$boolean_options"
}
_podman_stop() {
     local options_with_args="
     --timeout -t
     "
     local boolean_options="
     --all
     -a
     --latest
     -l"
     _complete_ "$options_with_args" "$boolean_options"
}

_podman_unpause() {
     local options_with_args="
     --help -h
     "
     local boolean_options=""
     _complete_ "$options_with_args" "$boolean_options"
}

_podman_wait() {
     local options_with_args=""
     local boolean_options="
        --help
        -h
        -l
        --latest"
     _complete_ "$options_with_args" "$boolean_options"
}

_complete_() {
    local options_with_args=$1
    local boolean_options="$2 -h --help"

    case "$prev" in
	$options_with_args)
	    return
	    ;;
    esac

    case "$cur" in
	-*)
	    COMPREPLY=( $( compgen -W "$boolean_options $options_with_args" -- "$cur" ) )
	    ;;
    esac
}

_podman_load() {
    local options_with_args="
    --input -i
    --signature-policy
    "
    local boolean_options="
    --quiet
    -q
    "
    _complete_ "$options_with_args" "$boolean_options"
}

_podman_login() {
     local options_with_args="
     --username
     -u
     --password
     -p
     --authfile
     "
     local boolean_options="
     --help
     -h
     "
     _complete_ "$options_with_args" "$boolean_options"
}

_podman_logout() {
     local options_with_args="
     --authfile
     "
     local boolean_options="
     --all
     -a
     --help
     -h
     "
     _complete_ "$options_with_args" "$boolean_options"
}

_podman_podman() {
     local options_with_args="
           --config -c
           --cpu-profile
           --root
           --runroot
           --storage-driver
           --storage-opt
           --log-level
    "
     local boolean_options="
           --help -h
           --version -v
     "
     commands="
    attach
    build
    commit
    create
    diff
    exec
    export
    history
    images
    import
    info
    inspect
    kill
    load
    login
    logout
    logs
    mount
    pause
    port
    ps
    pull
    push
    restart
    rm
    rmi
    run
    save
    search
    start
    stats
    stop
    tag
    top
    umount
    unmount
    unpause
    version
    wait
     "

     case "$prev" in
	 $main_options_with_args_glob )
	     return
	     ;;
     esac

     case "$cur" in
	 -*)
	     COMPREPLY=( $( compgen -W "$boolean_options $options_with_args" -- "$cur" ) )
	     ;;
	 *)
	     COMPREPLY=( $( compgen -W "${commands[*]} help" -- "$cur" ) )
	     ;;
     esac
}

_cli_bash_autocomplete() {
     local cur opts base

     COMPREPLY=()
     cur="${COMP_WORDS[COMP_CWORD]}"
     COMPREPLY=()
     local cur prev words cword

     _get_comp_words_by_ref -n : cur prev words cword

     local command=${PROG} cpos=0
     local counter=1
     counter=1
     while [ $counter -lt $cword ]; do
	 case "!${words[$counter]}" in
	     *)
		 command=$(echo "${words[$counter]}" | sed 's/-/_/g')
		 cpos=$counter
		 (( cpos++ ))
		 break
		 ;;
	 esac
	 (( counter++ ))
     done

     local completions_func=_podman_${command}
     declare -F $completions_func >/dev/null && $completions_func

     eval "$previous_extglob_setting"
     return 0
}

complete -F _cli_bash_autocomplete $PROG
