#autoload

setopt extendedglob bareglobqual
#Description:
# functions for gentoo packages
# inspired by _deb_packages
#Usage: _gentoo_packages installed|available|installed_versions|available_versions|binary|category|useflag

_parsesetsconf() {
  [[ -d ${1} ]] || continue

  local v f places sections setsconf insection section arr

  if [[ -d ${1}/sets ]]; then
    setsconf=(${1}/sets/*.conf(N))
     [[ (($#setsconf > 0)) ]] && places=(${setsconf})
  elif [[ -f ${1}/sets.conf ]]; then
    places=(${1}/sets.conf)
  fi

  for f in ${(@)places}; do
    if [[ -r ${f} ]]; then
      insection=0
      declare -A arr
      IFS='= '
      while read -r name value; do
        [[ -z ${name} || ${name} == '#'* ]] && continue

        if [[ (${name} == '['*']') && (-z ${value}) ]]; then
          value=${name//(\]|\[)}
          name="section"
        fi
        arr[${name}]=${value}

        if [[ ${insection} == 1 && ${name} == "section" ]]; then
          [[ ${2} == "sets" ]] && [[ ! ${value} =~ "sets" ]] && sections+=(${value})
          insection=0
        elif [[ ${name} == "section" ]]; then
          [[ ${value} =~ "${1:t} sets" ]] && insection=1
          [[ ${2} == "sets" ]] && [[ ! ${value} =~ "sets" ]] && sections+=(${value})
        elif [[ ${insection} == 1 ]]; then
          [[ ${2} == "sets" ]] && continue
          if [[ ${name} == "directory" ]]; then
            v=${value}
          fi
        fi
        continue
      done < ${f}
    fi
  done

  if [[ ${2} == "sets" ]]; then
    [[ ((${#sections} > 0)) ]] && echo ${(@)sections}
  else
    [[ ((${#v} > 0)) ]] && echo ${v:t}
  fi
}

_gentoo_packages_update_installed_sets() {
  local sets
  sets=($(<${EPREFIX}/var/lib/portage/world_sets))
  if [[ ((${#sets} > 0)) ]]; then
     _wanted installed_sets expl 'installed set' compadd "$@" "${(o@)^sets}"
  fi
}

_gentoo_packages_update_available_sets() {
  local dirs dir sets_dir set sets sets_path sets_files

  dirs=($(_gentoo_repos -o) ${EPREFIX}/etc/portage ${EPREFIX}/usr/share/portage/config)

  for dir in ${(@)dirs}; do
    if [[ -d ${dir} ]]; then
      sets_dir="$(_parsesetsconf ${dir})"
      [[ ! -z "${sets_dir}" ]] && sets_path="${dir}/${sets_dir}" || sets_path="${dir}/sets"
      if [[ -d "${sets_path}" ]]; then
        sets_files=(${sets_path}/*~*.conf(N))
        for set in ${sets_files[@]}; do
          sets+=(${set}(:t))
        done
        sets+=($(_parsesetsconf ${dir} sets))
      fi
    fi
  done
  if [[ ((${#sets} > 0)) ]]; then
     _wanted available_sets expl 'available set' compadd "$@" "@${(o@)^sets}"
  fi
}

# Completion function to show useflags.
_gentoo_packages_update_useflag(){
  local flags repo

  for repo in $(_gentoo_repos); do
    [[ -r ${repo}/profiles/use.desc ]] &&
      flags+=(${${(M)${(f)"$(<${repo}/profiles/use.desc)"}:#* - *}%% - *})
    [[ -r ${repo}/profiles/use.local.desc ]] &&
      flags+=(${${${(M)${(f)"$(<${repo}/profiles/use.local.desc)"}#* - *}%% - *}#*:})
  done

  compadd $flags
}

_gentoo_packages_update_active_useflag(){
  local flags USE
  var=USE
  [[ -z ${(P)var} && -r ${EPREFIX}/etc/portage/make.conf ]] &&
    local $var="$(. ${EPREFIX}/etc/portage/make.conf 2>/dev/null; echo ${(P)var})"
  [[ -z ${(P)var} && -r ${EPREFIX}/etc/make.conf ]] &&
    local $var="$(. ${EPREFIX}/etc/make.conf 2>/dev/null; echo ${(P)var})"
  flags=(${${${=USE}%-*}%\\*})
  compadd $flags
}

_gentoo_packages_update_category(){
  local repos category

  repos=($(_gentoo_repos))
  category=( $repos/*-*(/:t) )
  _wanted cat_packages expl 'category' compadd "$@" $category
}

_gentoo_packages_update_installed(){
   local installed_dir installed_portage installed_pkgname installed_list
   installed_dir="${EPREFIX}/var/db/pkg"
   installed_portage=($installed_dir/*-*/*)

   installed_pkgname=(${${installed_portage:t}%%-[0-9]*})
   _wanted packages expl 'package' compadd "$@" ${installed_pkgname}

   installed_list=( ${${installed_portage#$installed_dir/}%%-[0-9]*} )
   _wanted cat_packages expl 'category/package' _multi_parts "$@" / installed_list
}

_gentoo_packages_update_installed_versions(){
  local installed_list installed_portage

  installed_portage=(${EPREFIX}/var/db/pkg/*-*/*)
  _wanted packages expl 'package' compadd "$@" ${installed_portage:t}

  installed_list=(${installed_portage##*/pkg/})
  _wanted cat_packages expl 'category/package' _multi_parts "$@" / installed_list
}

_gentoo_packages_update_available_pkgnames_only(){
  local repos packages

  repos=($(_gentoo_repos))

  packages=($repos/*-*/*(:t))
  _wanted packages expl 'package' compadd - "${(@)packages}"
}

_gentoo_packages_update_available(){
  local repos category packages pkg expl

  repos=($(_gentoo_repos))
  category=($repos/*-*(/:t))

  packages=($repos/*-*/*(:t))
  _wanted packages expl 'package' compadd - "${(@)packages}"

  # Complete cat/pkg. _multi_parts is much to slow for such a large task,
  # _sep_parts removes the dash from gnome-<tab>, and _path_files wants to
  # complete cat/pkg/files (if "files" is ignored with -F, miscfiles, etc...
  # don't get completed).
  if [[ $PREFIX != */* ]]; then
    _wanted cat_packages expl 'category/package' compadd -S '/' $category
  else
    compset -P '*/'
    pkg=($repos/$IPREFIX/*(:t))
    _wanted cat_packages expl 'category/package' compadd $pkg
  fi
}

_gentoo_packages_update_available_versions(){
  local main_repo overlays overlay_ebuilds gentoo_ebuilds repos category pkg

  main_repo=$(_gentoo_repos -m)
  overlays=$(_gentoo_repos -o)

  repos=($main_repo $=overlays)
  category=($repos/*-*(/:t))
  typeset -U category

  if [[ $#PREFIX -ge 1 && -z $words[(r)(--inject|-i)] ]]; then
    overlay_ebuilds=($=overlays/*-*/${PREFIX%%-[0-9]#*}*/*.ebuild(:t:r) )
    gentoo_ebuilds=($main_repo/metadata/cache/*-*/${PREFIX%%-[0-9]#*}*(:t))
    _wanted packages expl 'package' compadd $gentoo_ebuilds $overlay_ebuilds
  fi
  pkg=( $repos/${PREFIX%%/*}/*/*.ebuild(:t:r) )
  _wanted cat_packages expl 'category/package' _sep_parts category / pkg
}

#Function to show tbz2 files available
_gentoo_packages_update_binary() {
  local PKGDIR

  [[ -z $PKGDIR && -r ${EPREFIX}/etc/portage/make.conf ]] &&
    PKGDIR="$(. ${EPREFIX}/etc/portage/make.conf 2>/dev/null; echo $PKGDIR)"
  [[ -z $PKGDIR && -r ${EPREFIX}/etc/make.conf ]] &&
    PKGDIR="$(. ${EPREFIX}/etc/make.conf 2>/dev/null; echo $PKGDIR)"
  [[ -z $PKGDIR && -r ${EPREFIX}/usr/share/portage/config/make.globals ]] &&
    PKGDIR="$(. ${EPREFIX}/usr/share/portage/config/make.globals 2>/dev/null; echo $PKGDIR)"

  # this doesn't take care of ${PORTAGE_BINHOST}. If Gentoo official
  # binary mirror will be available we should rewrite it accordingly.
  _path_files -g \*.tbz2 -W "$PKGDIR/All"
}

_gentoo_packages () {
  local command="$argv[$#]" expl cachevar pkgset update_policy

  zstyle -s ":completion:*:*:$service:*" cache-policy update_policy
  if [[ -z "$update_policy" ]]; then
    zstyle ":completion:*:*:$service:*" cache-policy _gentoo_cache_policy
  fi
  [[ "$command" == (installed(_versions|_sets|)|available(_versions|_sets|_pkgnames_only|)|binary|category|(active_|)useflag) ]] || {
    _message "unknown command: $command"
    return
  }
  [[ "$pkgset" == (installed(_versions|_sets|)|available(_versions|_sets|_pkgnames_only|)|binary|category|(active_|)useflag) ]] || {
    pkgset="$command"
  }
  expl=("${(@)argv[1,-2]}")
  _gentoo_packages_update_$pkgset
}

_gentoo_cache_policy () {
  local oldp

  # rebuild if cache is more than a week old
  oldp=( "$1"(mw+1) )
    (( $#oldp )) && return 0
}

_gentoo_packages "$@"

# vim: set et sw=2 ts=2 ft=zsh:
