## 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 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

    VCS_INFO_set-patch-format 'applied' 'applied_string' \
                              'unapplied' 'unapplied_string' \
                              ${context} qstring \
                              '' ''
    qstring=$REPLY

    case ${mode} in
    (standalone)
        backend_misc[patches]=${qstring}
        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 "$@"
