## vim:ft=zsh:foldmethod=marker

function VCS_INFO_quilt-match() {
    emulate -L zsh
    setopt extendedglob
    local d mode="$1" param="$2"
    local -a list

    case ${mode} in
        (assoc) list=( ${(kOP)param} );;
        (array) : "${foo[@]}" ${(t)foo}; list=( ${(OP)param} );;
        (*) return 1;;
    esac
    for d in "${list[@]}"; do
        if [[ ${PWD} == ${d%/##}(|/*) ]]; then
            print "$d"
            return 0
        fi
    done
    return 1
}

function VCS_INFO_quilt-standalone-detect() {
    emulate -L zsh
    setopt extendedglob
    local param
    local -i ret

    zstyle -s "${context}" quilt-standalone param || return 1
    [[ "${param}" == 'never' ]] && return 1
    [[ "${param}" == 'always' ]] && return 0

    if (( ${+functions[$param]} )); then
        ${param}
        return $?
    fi

    case ${(Pt)param} in
    *association*)
        local m
        local -A A
        m="$(VCS_INFO_quilt-match assoc ${param})"
        A=(${(kvP)param})
        (( $? == 0 )) && [[ ${A[$m]} == "true" ]] && return 0
        return 1
        ;;
    *array*)
        typeset -gU ${param}
        VCS_INFO_quilt-match array ${param} > /dev/null
        return $?
        ;;
    *scalar*)
        [[ "${(P)param}" == 'always' ]] && return 0
        [[ "${(P)param}" == 'never' ]] && return 1
        ;;
    esac
    # If nothing hit yet, it just wasn't meant to be.
    return 1
}

function VCS_INFO_quilt-dirfind() {
    # This is a wrapper around VCS_INFO_bydir_detect(). It makes sure
    # that $vcs_comm[] is unchanged. Currently, changing anything in it
    # should not be an issue, but this makes sure the code can safely
    # be called elsewhere, too - if needed.
    emulate -L zsh
    setopt extendedglob
    local dir="$1" file="$2"; shift $#
    local ret oldfile olddir

    olddir=${vcs_comm[basedir]}
    vcs_comm[basedir]=''
    oldfile=${vcs_comm[detect_need_file]}
    vcs_comm[detect_need_file]=${file}
    VCS_INFO_bydir_detect ${dir}
    ret=$?
    vcs_comm[detect_need_file]=${oldfile}
    printf '%s' ${vcs_comm[basedir]}
    vcs_comm[basedir]="${olddir}"
    return ${ret}
}

function VCS_INFO_quilt-patch2subject() {
    VCS_INFO_patch2subject "$@"
}

function VCS_INFO_quilt() {
    emulate -L zsh
    setopt extendedglob
    local mode="$1"
    local patches pc tmp qstring root
    local -i ret
    local context
    local -a applied unapplied all applied_string unapplied_string quiltcommand quilt_env
    local -A hook_com

    context=":vcs_info:${vcs}.quilt-${mode}:${usercontext}:${rrn}"
    zstyle -t "${context}" use-quilt || return 1

    case ${mode} in
    (standalone)
        VCS_INFO_quilt-standalone-detect || return 1
        ;;
    (addon)
        ;;
    (*)
        printf 'Invalid mode: `%s'\''\n' "$1"
        return 2
        ;;
    esac

    pc="$(VCS_INFO_quilt-dirfind .pc .version)"
    ret=$?
    if (( ret == 0 )); then
        [[ ${quiltmode} == 'standalone' ]] && root=${pc}
        pc=${pc}/.pc
        if [[ -e ${pc}/applied-patches ]]; then
            applied=( ${(f)"$(<$pc/applied-patches)"} )
            # throw away empty entries
            applied=( ${applied:#} )
            applied=( ${(Oa)applied} )
        else
            applied=()
        fi
        patches=$(<$pc/.quilt_patches)
        patches=`builtin cd -q "${pc:h}" && print -r - ${patches:P}`
    fi
    if zstyle -t "${context}" get-unapplied; then
        # This zstyle call needs to be moved further up if `quilt' needs
        # to be run in more places than this one.
        zstyle -s "${context}" quiltcommand quiltcommand || quiltcommand='quilt'
        quilt_env=(env)
        if [ -z "$patches" ]; then
            zstyle -s "${context}" quilt-patch-dir patches || patches="${QUILT_PATCHES}"
            if [[ "${patches}" != /* ]]; then
                tmp=${patches:-patches}
                patches="$(VCS_INFO_quilt-dirfind "${tmp}")"
                ret=$?
                (( ret )) && return ${ret}
                patches=${patches}/${tmp}
            else
                [[ -d ${patches} ]] || return 1
            fi
            quilt_env+=(QUILT_PATCHES="$patches")
        fi
        unapplied=( ${(f)"$(${quilt_env[@]} $quiltcommand --quiltrc /dev/null unapplied 2> /dev/null)"} )
        unapplied=( ${unapplied:#} )
    else
        unapplied=()
    fi

    if [[ -n $patches ]]; then
      () {
        local i
        for ((i=1; i<=$#applied; i++)); do
          if VCS_INFO_quilt-patch2subject "$patches/$applied[$i]" && (( $+REPLY ))
          then
            applied[$i]+=" $REPLY"
          else
            applied[$i]+=" ?"
          fi
        done
        for ((i=1; i<=$#unapplied; i++)); do
          if VCS_INFO_quilt-patch2subject "$patches/$unapplied[$i]" && (( $+REPLY ))
          then
            unapplied[$i]+=" $REPLY"
          else
            unapplied[$i]+=" ?"
          fi
        done
      }
    fi

    all=( ${(Oa)applied} ${unapplied} )

    if VCS_INFO_hook 'gen-applied-string' "${applied[@]}"; then
        if (( ${#applied} )); then
            applied_string=${applied[1]}
        else
            applied_string=""
        fi
    else
        applied_string=${hook_com[applied-string]}
    fi
    hook_com=()
    if VCS_INFO_hook 'gen-unapplied-string' "${unapplied[@]}"; then
        unapplied_string="${#unapplied}"
    else
        unapplied_string=${hook_com[unapplied-string]}
    fi

    if (( ${#applied} )); then
        zstyle -s "${context}" patch-format qstring || qstring="%p (%n applied)"
    else
        zstyle -s "${context}" nopatch-format qstring || qstring="no patch applied"
    fi
    hook_com=( applied "${applied_string}" unapplied "${unapplied_string}"
               applied-n ${#applied}       unapplied-n ${#unapplied}       all-n ${#all} )
    if VCS_INFO_hook 'set-patch-format' ${qstring}; then
        zformat -f qstring "${qstring}" "p:${hook_com[applied]}" "u:${hook_com[unapplied]}" \
                                        "n:${#applied}" "c:${#unapplied}" "a:${#all}"
    else
        qstring=${hook_com[patch-replace]}
    fi
    hook_com=()

    case ${mode} in
    (standalone)
        VCS_INFO_formats '' '' "${root}" '' '' '' "${qstring}"
        VCS_INFO_set
        ;;
    (addon)
        # When VCS_INFO_quilt() is called with "addon" a "local REPLY" variable
        # should be in place. That variable can be unset after it's being used.
        REPLY="${qstring}"
        ;;
    esac

    VCS_INFO_hook 'post-quilt' ${mode} ${patches} ${pc:-\\-nopc-}
}
VCS_INFO_quilt "$@"
