# -*- shell-script -*-
# Copyright (C) 2017 Dmitry Bogatov
#
# 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
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# 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, see <http://www.gnu.org/licenses/>.
#

# Ticket is represented by directory in 'ticgit' branch, which has
# TICKET_ID file with directory name in it.
#
# Real ticketId, as references by all subcommands of 'ticgit' is a
# hash of blob, corresponding to content of that TICKET_ID file.
#
# This function enumerates all tickets with ID starting with ${1}.
#
# Use of low-level representation of TicGit tickets and Git blobs is about
# factor 30 faster than parsing output of `ti list'.
_ticgit_tickets () {
    local prefix=${1};
    local names=$(git ls-tree -d --name-only ticgit 2>/dev/null) || return

    for name in ${names} ; do
        ticket=$(printf "blob %d\0%s\n" $(( 1 + ${#name})) "${name}"|sha1sum)
        if [[ $prefix = "${ticket:0:${#prefix}}" ]] ; then
            echo "${ticket:0:6}"
        fi
    done
}

_ticgit_tags () {
    local prefix=${1}
    local tree=$(git ls-tree -r ticgit --name-only 2>/dev/null) || return
    for tag in $(echo "${tree}" | awk -FTAG_ '{ print $2 }') ; do
        if [[ $prefix = "${tag:0:${#prefix}}" ]] ; then
            echo "${tag}"
        fi
    done
}

_ticgit_complete_ticket_or_options () {
    case "${cur}" in
        -*) COMPREPLY=($(compgen -W "${options}" -- "${cur}")) ;;
        *) COMPREPLY=($(_ticgit_tickets "${cur}")) ;;
    esac
}

# Completion functions for specific subcommands
_ticgit_complete_show () {
    local options='--help --version --full'
    _ticgit_complete_ticket_or_options
}

_ticgit_complete_assign () {
    local options='--version --help --user --checkout'
    case "${prev}" in
        -c|--checkout) COMPREPLY=($(_ticgit_tickets "${cur}")) ;;
        -u|--user) ;; # FIXME: how to complete user?
        *) _ticgit_complete_ticket_or_options ;;
    esac
}

_ticgit_complete_checkout () {
    local options='--help --version'
    _ticgit_complete_ticket_or_options
}

_ticgit_complete_comment () {
    local options='--help --version --file --message'
    case "${prev}" in
        -f|--file) _filedir ;;
        -m|--message) ;;
        *) _ticgit_complete_ticket_or_options ;;
    esac
}

_ticgit_complete_list () {
    local options='--help --version --list --saveas --assigned
        --states --tags --order'
    case "${prev}" in
        -S|--saveas) ;;
        -a|--assigned) #FIXME: not implemented
            ;;
        -t|--tags) COMPREPLY=($(_ticgit_tags "$cur")) ;;
        -s|--states)
            COMPREPLY=($(compgen -W "$states" -- "$cur"))
            ;;
        -o|--order)
            local orders='assigned state date title'
            COMPREPLY=($(compgen -W "$orders" -- "$cur"))
            ;;
        *) COMPREPLY=($(compgen -W "$options" -- "$cur")) ;;
    esac
}

_ticgit_complete_new () {
    local options='--help --version --title'
    case "${prev}" in
        -t|--title) ;;
        *) _ticgit_complete_ticket_or_options ;;
    esac
}

_ticgit_complete_points () {
    local options='--help --version'
    if [[ $cword -eq 2 ]] ; then
        _ticgit_complete_ticket_or_options
    fi
}

_ticgit_complete_state () {
    if [[ $cword -eq 2 ]] ; then
        COMPREPLY=( $(_ticgit_tickets "${cur}")
                    $(compgen -W "${states}" -- "${cur}") )
    else
        COMPREPLY=( $(compgen -W "${states}" -- "${cur}") )
    fi
}

_ticgit_complete_tag () {
    if [[ $cword -eq 2 ]] ; then
	COMPREPLY=( $(_ticgit_tickets "${cur}") )
    else
	COMPREPLY=( $(compgen -W "--delete" -- "${cur}")
		    $(_ticgit_tags "${cur}") )
    fi
}

_ticgit () {
    local states='hold invalid open resolved'
    local cur prev word cword
    _init_completion || return

    local commands='assign checkout comment help init list new points
        recent show state sync tag'

    if [[ $cword -eq 1 ]] ; then
        COMPREPLY=($(compgen -W "$commands" -- "$cur"))
    else
        case ${COMP_WORDS[1]} in
            help) COMPREPLY=($(compgen -W "$commands" -- "$cur")) ;;
            init|resent)
                COMPREPLY=($(compgen -W '--help --version' -- "$cur"))
                ;;
            assign)     _ticgit_complete_assign         ;;
            checkout)   _ticgit_complete_checkout       ;;
            comment)    _ticgit_complete_comment        ;;
            list)       _ticgit_complete_list           ;;
            new)        _ticgit_complete_new            ;;
            points)     _ticgit_complete_points         ;;
            show)       _ticgit_complete_show           ;;
            state)      _ticgit_complete_state          ;;
            sync)       _ticgit_complete_sync           ;;
            tag)        _ticgit_complete_tag            ;;
        esac
    fi
}

complete -F _ticgit ti
# vim: ft=sh
