#compdef zplug

local    curcontext="$curcontext" state
local    p desc
local -i ret=1
local -a -U zplug_cmds
local -a _zplug_boolean_true _zplug_boolean_false
local -a cmds tags

cmds=( "${(k)_zplug_commands[@]}" )
tags=( "${(k)_zplug_tags[@]}" )

_zplug_boolean_true=("true" "yes" "on" 1)
_zplug_boolean_false=("false" "no" "off" 0)

# Completions of zplug commands
for p in "${(k)_zplug_commands[@]}"
do
    zplug_cmds+=("$p:$_zplug_commands[$p]")
done

# Completions for user-defined commands
for p in ${^path}/zplug-*(N-.)
do
    desc=
    desc="$(grep -E "^# Desc(ription)?: ?" "$p")"
    regexp-replace desc "^.*[Dd]esc(ription)?: ?" ""
    desc="[User-defined] ${desc:-"No description."}"
    zplug_cmds+=("${p:t:gs:zplug-:}:$desc")
done
# Completions for user-defined functions
for p in ${(M)${(k)functions[@]}:#zplug-*}
do
    f=( ${^fpath[@]}/$p(N) )
    desc=
    if [[ -f $f[1] ]]; then
        desc="$(grep -E "^# Desc(ription)?: ?" "$f[1]")"
        regexp-replace desc "^.*[Dd]esc(ription)?: ?" ""
    fi
    desc="[User-defined] ${desc:-"No description."}"
    zplug_cmds+=("${p:gs:zplug-:}:$desc")
done

_arguments \
    "(-)--help[$_zplug_options[help]]: :->comp" \
    "(-)--version[$_zplug_options[version]]: :" \
    "(-)--log=[$_zplug_options[log]]: :->log" \
    "(-)--rollback=[$_zplug_options[rollback]]: :->rollback" \
    "(-)--self-manage[$_zplug_options[self-manage]]: :" \
    "*:: :->comp" && return 0

if (( CURRENT == 1 )); then
    _describe -t commands "zplug subcommand" zplug_cmds
    return 0
fi

case "$words[1]" in
    check)
        _arguments \
            '(--verbose)--verbose[show non-installed items in output]' \
            '*:: :( "${(uk)zplugs[@]:gs:@::}" )'
        ret=0
        ;;
    install)
        _arguments \
            '(--verbose)--verbose[show non-installed items in output]' \
            '(--select)--select[select items with interactive filters]' \
            '*:: :compadd -X "%F{green}Accept%f %Busername/reponame%b arguments"'
        ret=0
        ;;
    load)
        _arguments \
            '(--verbose)--verbose[display loading files]'
        ret=0
        ;;
    status|update)
        _arguments \
            '(--select)--select[select items with interactive filters]' \
            '*:: :( "${(uk)zplugs[@]:gs:@::}" )'
        ret=0
        ;;
    list)
        _arguments \
            '(--loaded --installed)--loaded[list loaded packages]' \
            '(--loaded --installed)--installed[list installed packages]' \
            '(--select)--select[list packages and select them]'
        ret=0
        ;;
    clean)
        _arguments \
            '(--force --select)--force[force the removing activity]' \
            '(--select --force)--select[select items with interactive filters]' \
            '*:: :( "${(uk)zplugs[@]:gs:@::}" )'
        ret=0
        ;;
    clear)
        _arguments \
            '(--force)--force[force the removing activity]'
        ret=0
        ;;
    info)
        _arguments \
            '*:: :( "${(uk)zplugs[@]:gs:@::}" )'
        ret=0
        ;;
    */*)
        if ! [[ $BUFFER =~ ", $" || $BUFFER =~ ":$" ]]; then
            return 0
        fi
        _values -S : -s , "zplug tags" \
            "as[$_zplug_tags[as]]:as:(plugin command theme)" \
            "use[$_zplug_tags[use]]:use:->use" \
            "from[$_zplug_tags[from]]:from:(gh-r gist oh-my-zsh github gitlab bitbucket local)" \
            "at[$_zplug_tags[at]]:at:" \
            "rename-to[$_zplug_tags[rename-to]]:rename-to:" \
            "dir[$_zplug_tags[dir]]:dir:->dir" \
            "if[$_zplug_tags[if]]:if:" \
            "hook-build[$_zplug_tags[hook-build]]:hook-build:" \
            "hook-load[$_zplug_tags[hook-load]]:hook-load:" \
            "frozen[$_zplug_tags[frozen]]:frozen:->boolean" \
            "on[$_zplug_tags[on]]:on:->on" \
            "defer[$_zplug_tags[defer]]:defer:->defer" \
            "ignore[$_zplug_tags[ignore]]:ignore:" \
            "lazy[$_zplug_tags[lazy]]:lazy:->boolean" \
            "depth[$_zplug_tags[depth]]:depth:({0..10})" && ret=0
        case $state in
            on|dir)
                compadd -X "%F{green}READ ONLY%f %Bno arguments%b"
                ;;
            use)
                compadd -J 'command/plugin' -X "%F{yellow}Completing%f %BExample patterns%b" \
                    '*.zsh' \
                    '*.sh' \
                    'zsh/*.zsh' \
                    '*.plugin.zsh' \
                    'init.zsh'
                compadd -J 'gh-r' -X "%F{yellow}Completing%f %BGitHub Releases (example)%b" \
                    'amd64' \
                    'darwin*amd64' \
                    'linux*amd64' \
                    '386' \
                    'darwin*386' \
                    'linux*386' \
                    'darwin' \
                    'linux'
                ;;
            defer)
                compadd -V 'default' -X "%F{yellow}Completing%f %Bpriority (default)%b" 0
                compadd -V 'defer' -X "%F{yellow}Completing%f %Bpriority%b" -- 1
                compadd -V 'after_compinit' -X "%F{yellow}Completing%f %Bpriority (after compinit)%b" 2 3
                ;;
            boolean)
                compadd -J 'boolean/true' -X "%F{yellow}Completing%f %Btrue word%b" $_zplug_boolean_true
                compadd -J 'boolean/false' -X "%F{yellow}Completing%f %Bfalse word%b" $_zplug_boolean_false
                ;;
        esac
        return ret
        ;;
esac

case $state in
    "comp")
        _describe -t help_cmds "commands" cmds
        _describe -t help_tags "tags" tags
        ;;
    "log")
        local _log_args
        _log_args=(
        'less' 'more' 'edit'
        'clear' 'count' 'latest'
        )
        if (( $+commands[jq] )); then
            _log_args+=("jq")
        fi
        _describe -t 'log' 'log' _log_args && ret=0
        ;;
    "rollback")
        local _rollback_args
        _rollback_args=( 'build' )
        _describe -t 'rollback' 'rollback' _rollback_args && ret=0
        ;;
esac

return ret
