#-----------------------------------------------------------
# Copyright Christian Arnault LAL-Orsay CNRS
# arnault@lal.in2p3.fr
# Written by Grigory Rybkin
# See the complete license in cmt_license.txt "http://www.cecill.info". 
#-----------------------------------------------------------

shopt -s extglob

_cmt_escape_compreply ()
{
    local i
    for ((i=0; i < ${#COMPREPLY[*]}; i++)); do
	[[ ! ${COMPREPLY[$i]} =~ ["${COMP_WORDBREAKS/$'\n'}"] ]] || \
	COMPREPLY[$i]=$(sed "s,[${COMP_WORDBREAKS/$'\n'}],\\\\&,g" <<<"${COMPREPLY[$i]}")
    done
}

_cmt ()
{
    local commands=(broadcast build check check_files checkout co cleanup config create create_project expand filter help lock relocate remove run setup show system unlock version ${CVSROOT:+cvstags cvsbranches cvssubpackages cvssubprojects})
    local with_subcommands=(build check expand remove show)
    local global_opts=(-disable_warnings -quiet -use= -pack= -version= -path= -f= -e= -tag= -tag_add= -tag_remove= -warnings -with_version_directory -without_version_directory -cleanup -no_cleanup -xml)
    local broadcast_opts=(-begin= -select= -exclude= -local -global -depth=)
    local build_subcmds=(CMT_pacman constituent_makefile constituents_makefile dependencies library_links make_setup msdev os9_makefile prototype readme tag_makefile temporary_name triggers win_makefile)
    local check_subcmds=(configuration files version)
    local show_subcmds=(action action_names action_value actions alias alias_names alias_value aliases all_tags applied_patterns author branches clients cmtpath_patterns constituent constituent_names constituents container cycles fragment fragments groups include_dirs language languages macro macro_names macro_value macros manager packages path pattern patterns projects project_author pwd set set_names set_value sets strategies tags use_paths uses versions)

    local cur _IFS="${IFS}"
    local i opts _COMPREPLY p mwds wordlist

    COMPREPLY=()
    cur=$2
    
    local iself= icommand= command= isubcommand= subcommand=
    for ((i=0; i < COMP_CWORD; i++)); do
	if [ -z $iself ]; then
	    [[ ${COMP_WORDS[i]} == $1 ]] && { iself=$i; }
	    continue
	fi
	if [ -z $icommand ]; then
	    # global options
	    [[ ${COMP_WORDS[i]} == -* ]] && { continue; }
#	    _IFS="${IFS}"
	    IFS="|"
	    commands_pattern="${commands[*]}"
	    IFS="${_IFS}"
	    if [[ ${COMP_WORDS[i]} == @(${commands_pattern}) ]]; then
		command=${COMP_WORDS[i]}; icommand=$i
	    fi
	    continue
	fi
	if [ -z $isubcommand ]; then
	    # command options
	    [[ ${COMP_WORDS[i]} == -* ]] && { continue; }
#	    _IFS="${IFS}"
	    IFS="|"
	    with_subcommands_pattern="${with_subcommands[*]}"
	    IFS="${_IFS}"
	    if [[ $command == @(${with_subcommands_pattern}) ]]; then
		subcommand=${COMP_WORDS[i]}; isubcommand=$i
	    fi
	    continue
	fi
    done

    [ -z $iself ] && return 0

    if [ -n "$isubcommand" ]; then
	case $command in
	    build)
		case $subcommand in
		    constituent_makefile|triggers)
			if (( isubcommand + 1 == COMP_CWORD )); then
			    COMPREPLY=($(compgen -W "$(cmt -quiet show constituent_names)" -- "$cur"))
			fi
			;;
		esac
		;;
	    check)
		case $subcommand in 
		    files)
			if (( isubcommand + 1 == COMP_CWORD ||
				    isubcommand + 2 == COMP_CWORD )); then
			    return 0
			    IFS=$'\n'
			    COMPREPLY=( $( compgen -f -- "${cur}" ) )
			    IFS="${_IFS}"
			    _cmt_escape_compreply
			fi
			;;
		esac
		;;
	    remove)
		case $subcommand in 
		    library_links)
			;;
		    *)
			if (( icommand + 3 == COMP_CWORD )); then
			    return 0
			    IFS=$'\n'
			    COMPREPLY=( $( compgen -f -- "${cur}" ) )
			    IFS="${_IFS}"
			    _cmt_escape_compreply
			fi
			;;  
		esac
		;;
	    show)
		case $subcommand in
		    constituent)
			if (( isubcommand + 1 == COMP_CWORD )); then
			    COMPREPLY=($(compgen -W "$(cmt -quiet show constituent_names)" -- "$cur"))
			fi
			;;
		    fragment)
			if (( isubcommand + 1 == COMP_CWORD )); then
			    COMPREPLY=($(compgen -W "$(cmt -quiet show fragments | sed 's#.*/fragments/##')" -- "$cur"))
			fi
			;;
		    action|action_value)
			if (( isubcommand + 1 == COMP_CWORD )); then
			    COMPREPLY=($(compgen -W "$(cmt -quiet show action_names)" -- "$cur"))
			fi
			;;
		    alias|alias_value)
			if (( isubcommand + 1 == COMP_CWORD )); then
			    COMPREPLY=($(compgen -W "$(cmt -quiet show alias_names)" -- "$cur"))
			fi
			;;
		    macro|macro_value)
			if (( isubcommand + 1 == COMP_CWORD )); then
			    COMPREPLY=($(compgen -W "$(cmt -quiet show macro_names)" -- "$cur"))
			fi
			;;
		    pattern)
			if (( isubcommand + 1 == COMP_CWORD )); then
			    COMPREPLY=($(compgen -W "$(cmt -quiet show pattern_names)" -- "$cur"))
			fi
			;;
		    set|set_value)
			if (( isubcommand + 1 == COMP_CWORD )); then
			    COMPREPLY=($(compgen -W "$(cmt -quiet show set_names)" -- "$cur"))
			fi
			;;
		esac
		;;
	esac
    elif [ -n "$icommand" ]; then
	case $command in
	    broadcast|run)
		IFS=$'\n'
		COMPREPLY=($(compgen -c -- "$cur"))
		IFS="${_IFS}"
		_cmt_escape_compreply
		[ "$command" = run ] && return 0
		opts=1
		for (( i=(icommand + 1); i < COMP_CWORD; i++ )); do
		    [[ ${COMP_WORDS[i]} != -* ]] && { opts=; break; }
		done
		if [ -n "$opts" ]; then
		    _COMPREPLY=($(compgen -W "${broadcast_opts[*]}" -- "$cur"))
		    COMPREPLY=("${_COMPREPLY[@]}" "${COMPREPLY[@]}")
		fi
		;;
	    build)
		if (( icommand + 1 == COMP_CWORD )); then
		    COMPREPLY=($(compgen -W "${build_subcmds[*]}" -- "$cur"))
		fi
		;;
	    check)
		if (( icommand + 1 == COMP_CWORD )); then
		    COMPREPLY=($(compgen -W "${check_subcmds[*]}" -- "$cur"))
		fi
		;;
	    check_files)
		if (( icommand + 1 == COMP_CWORD ||
			    icommand + 2 == COMP_CWORD )); then
		    return 0
		    IFS=$'\n'
		    COMPREPLY=( $( compgen -f -- "${cur}" ) )
		    IFS="${_IFS}"
		    _cmt_escape_compreply
		fi
		;;
	    create)
		if (( icommand + 3 == COMP_CWORD )); then
		    return 0
		    COMPREPLY=( $( compgen -f -- "${cur}" ) )
		fi
		;;
	    expand)
		if (( icommand + 1 == COMP_CWORD )); then
		    COMPREPLY=($(compgen -W "model" -- "$cur"))
		fi
		;;
	    remove)
		if (( icommand + 3 == COMP_CWORD )); then
		    return 0
		    COMPREPLY=( $( compgen -f -- "${cur}" ) )
		elif (( icommand + 1 == COMP_CWORD )); then
		    COMPREPLY=($(compgen -W "library_links" -- "$cur"))
		fi
		;;
	    show)
		if (( icommand + 1 == COMP_CWORD )); then
		    COMPREPLY=($(compgen -W "${show_subcmds[*]}" -- "$cur"))
		fi
		;;
	    co|checkout)
		case $3 in
		    -vd|-d)
			IFS=$'\n'
			COMPREPLY=( $( compgen -d -- "${cur}" ) )
			IFS="${_IFS}"
			_cmt_escape_compreply
			;;
		    -requirements)
			return 0
			COMPREPLY=( $( compgen -f -- "${cur}" ) )
			;;
		    *)
			COMPREPLY=($(compgen -W "-l -R -r -C -i -vd -d -o -requirements -no_config -rs --help" -- "${cur}"))
			;;
#		COMPREPLY=($(compgen -P "-" -W "l R r C i vd d o requirements no_config rs -help" -- ${cur#-}))
		esac
		;;
	esac
    else
	if [[ ${COMP_LINE:0:${COMP_POINT}} =~ ^.*-((path|f)=|(use)=([^:]+:){2}) ]] ; then
 	    p=${COMP_LINE:${#BASH_REMATCH[0]}:$(($COMP_POINT - ${#BASH_REMATCH[0]}))}
	    [ ${#p} -eq 0 ] && return 0
	    eval mwds=(${p}) 2>/dev/null || return 0
	    [ ${#mwds[*]} -le 1 ] && [ -n "${cur}" ] && return 0
	fi
	if [ "$3" = make ]; then
	    wordlist="$(cmt -quiet show constituent_names)"
	    wordlist="${wordlist} $(cmt -quiet show groups)"
	    wordlist="${wordlist} check all binclean help"
	    COMPREPLY=($(compgen -W "${wordlist}" -- "$cur"))
	    return 0
	fi
	wordlist="${global_opts[*]} ${commands[*]}"
	COMPREPLY=($(compgen -W "${wordlist}" -- "$cur"))
    fi
    
    return 0
}

complete -o default -F _cmt cmt
