#
# Copyright (c) - 2012 Simon Marchi <simon.marchi@polymtl.ca>
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by as published by
# the Free Software Foundation; only version 2 of the License.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
# more details.
#
# You should have received a copy of the GNU General Public License along with
# this program; if not, write to the Free Software Foundation, Inc., 51
# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#

# Generates COMPREPLY with the existing session names
_lttng_complete_sessions() {
	# TODO
	# This code does nothing for now. When there is a mecanism to get the
	# existing sessions, use it to fill the sessions variable.
	local sessions
	sessions=""
	COMPREPLY=( $(compgen -W "${sessions}" -- $cur) )
	return
}

# Generates COMPREPLY with whatever is in the $options variable.
_lttng_complete_options() {
	COMPREPLY=( $(compgen -W "${options}" -- $cur) )
}

# Generates COMPREPLY with whatever is in the $commands variable.
_lttng_complete_commands() {
	COMPREPLY=( $(compgen -W "${commands}" -- $cur) )
}

_lttng_cmd_addcontext() {
	options=$(lttng add-context --list-options)

	case $prev in
	--session|-s)
		_lttng_complete_sessions
		return
		;;
	--channel|-c)
		return
		;;
	--type|-t)
		return
		;;
	esac

	case $cur in
	-*)
		_lttng_complete_options
		return
		;;
	esac
}

_lttng_cmd_calibrate() {
	options=$(lttng calibrate --list-options)

	case $cur in
	-*)
		_lttng_complete_options
		return
		;;
	esac
}

_lttng_cmd_create() {
	options=$(lttng create --list-options)

	case $prev in
	--output|-o)
		_filedir -d
		return
		;;
	esac

	case $cur in
	-*)
		_lttng_complete_options
		return
		;;
	esac
}

_lttng_cmd_destroy() {
	options=$(lttng destroy --list-options)

	case $cur in
	-*)
		_lttng_complete_options
		return
		;;
	*)
		_lttng_complete_sessions
		return
		;;
	esac
}
_lttng_cmd_disablechannel() {
	options=$(lttng disable-channel --list-options)

	case $prev in
	--session|-s)
		_lttng_complete_sessions
		return
		;;
	esac

	case $cur in
	-*)
		_lttng_complete_options
		return
		;;
	esac
}
_lttng_cmd_disableevent() {
	options=$(lttng disable-event --list-options)

	case $prev in
	--session|-s)
		_lttng_complete_sessions
		return
		;;
	--channel|-c)
		return
		;;
	esac

	case $cur in
	-*)
		_lttng_complete_options
		return
		;;
	esac
}

_lttng_cmd_enablechannel() {
	options=$(lttng enable-channel --list-options)

	case $prev in
	--session|-s)
		_lttng_complete_sessions
		return
		;;
	esac

	case $cur in
	-*)
		_lttng_complete_options
		return
		;;
	esac
}

_lttng_cmd_enableevent() {
	options=$(lttng enable-event --list-options)

	case $prev in
	--session|-s)
		_lttng_complete_sessions
		return
		;;
	--channel|-c)
		return
		;;
	--probe)
		return
		;;
	--function)
		return
		;;
	esac

	case $cur in
	-*)
		_lttng_complete_options
		return
		;;
	esac
}

_lttng_cmd_list() {
	options=$(lttng list --list-options)

	case $prev in
	--channel|-c)
		return
		;;
	esac

	case $cur in
	-*)
		_lttng_complete_options
		return
		;;
	*)
		_lttng_complete_sessions
		return
	esac
}

_lttng_cmd_setsession() {
	options=$(lttng set-session --list-options)

	case $cur in
	-*)
		_lttng_complete_options
		return
		;;
	*)
		_lttng_complete_sessions
		return
		;;
	esac
}

_lttng_cmd_snapshot() {
	options=$(lttng snapshot --list-options)
	commands=$(lttng snapshot --list-commands)

	_lttng_find_command $((command_found_index + 1))

	if _lttng_cursor_is_after_command; then
		case $prev in
		--session|-s)
			_lttng_complete_sessions
			return
			;;
		esac

		case $cur in
		-*)
			_lttng_complete_options
			;;
		esac
	else
		_lttng_complete_commands
	fi
}

_lttng_cmd_start() {
	options=$(lttng start --list-options)

	case $cur in
	-*)
		_lttng_complete_options
		return
		;;
	*)
		_lttng_complete_sessions
		return
		;;
	esac
}

_lttng_cmd_stop() {
	options=$(lttng stop --list-options)

	case $cur in
	-*)
		_lttng_complete_options
		;;
	*)
		_lttng_complete_sessions
		;;
	esac
}

_lttng_cmd_version() {
	options=$(lttng version --list-options)

	case $cur in
	-*)
		_lttng_complete_options
		;;
	esac
}

_lttng_cmd_view() {
	options=$(lttng view --list-options)

	case $cur in
	-*)
		_lttng_complete_options
		;;
	esac
}



_lttng_before_command() {
	# Check if the previous word should alter the behavior
	case $prev in
	--group|-g)
		COMPREPLY=( $(compgen -g -- $cur) )
		return
		;;
	--sessiond-path)
		_filedir
		return
		;;
	esac

	case $cur in
	-*)
		# If the current word starts with a dash, complete with options
		_lttng_complete_options
		;;
	*)
		# Otherwise complete with commands
		_lttng_complete_commands
		;;
	esac
}

_lttng_after_command() {
	local cmd_name

	cmd_name=_lttng_cmd_${command_found//-/}

	type -t $cmd_name | grep -q 'function' && $cmd_name
}

# Check if the word passed as the first parameter corresponds to a
# command. $command must be set to the list of possible commands.
_lttng_is_command() {
	for command in $commands; do
		if [ "$1" == "$command" ]; then
			return 0
		fi
	done

	return 1
}

# Try to find a command in the current command line. Possible commands
# are passed in $commands.
#
# This function takes an optional parameter that indicates the index
# where to start the search in COMP_WORDS. If omitted, it defaults to 1.
#
# If a command is found, $command_found is filled with the name of the
# command and $command_found_index is set to the index of the command in
# $COMP_WORDS. If no command is found, $command_found is an empty string
# and $command_found_index is set to -1.
_lttng_find_command() {
	start=${1:-1}

	# The text of the found command
	command_found=""

	# The index of the found command in COMP_WORDS
	command_found_index=-1

	for (( i = start ; i < ${#COMP_WORDS[@]} ; i++ )); do
		_lttng_is_command ${COMP_WORDS[$i]}
		if [ $? -eq 0 ]; then
			command_found=${COMP_WORDS[$i]}
			command_found_index=$i
			break
		fi
	done
}

_lttng_cursor_is_after_command() {
	[ -n "$command_found" ] && [ "$COMP_CWORD" -gt "$command_found_index" ]
}

_lttng() {
	local cur prev commands command_found command_found_index

	# Get the current and previous word
	_get_comp_words_by_ref cur prev

	# Get the valid first-level LTTng commands and options
	commands=$(lttng --list-commands)
	options=$(lttng --list-options)

	_lttng_find_command

	# Check if the cursor is before or after the command keyword
	if _lttng_cursor_is_after_command; then
		_lttng_after_command
	else
		_lttng_before_command
	fi
}

complete -F _lttng lttng
