#compdef equery euse eclean eclean-dist eclean-pkg epkginfo eshowkw genpkgindex glsa-check revdep-rebuild

# XXX: shouldn't this go to _gentoo_package?
_packages () {
  if compset -P '(\\|)(>=|<=|<|>|=)'; then
    _gentoo_packages ${*/(#m)(installed|available)/${MATCH}_versions}
  else
    _gentoo_packages $*
  fi
}

_euse () {
  local state tmp start_args suboptions_args

  start_args=(
    {'(--help)-h','(-h)--help'}'[show help]'
    {'(--version)-v','(-v)--version'}'[show version]'
    {'(--info)-i','(-i)--info'}'[show descriptions for the given useflags]'
    {'(--info-installed)-I','(-I)--info-installed'}'[show descriptions for the given useflags and their current impact on the installed system]'
    {'(--active)-a','(-a)--active'}'[show currently active useflags and their origin]'
    {'(--enable)-E','(-E)--enable'}'[enable the given useflags]'
    {'(--disable)-D','(-D)--disable'}'[disable the given useflags]'
    {'(--remove)-R','(-R)--remove'}'[remove all references to the given flags from make.conf and package.use to revert to default settings]'
    {'(--prune)-P','(-P)--prune'}'[alias for --remove]'
    {'(--package)-p','(-p)--package'}'[used with -E, -D, and -R to apply to a specific package only]'
  )

  suboptions_args=(
    {'(--global)-g','(-g)--global'}'[show only global use flags]'
    {'(--local)-l','(-l)--local'}'[show only local use flags]'
  )

  if (( CURRENT == 2 )); then
    _arguments -s $start_args
  elif (( CURRENT == 3 )); then
    case "$words[2]" in
      -i|--info|-a|--active)
    _arguments -s $suboptions_args \
      '*:useflags:_gentoo_packages useflag' && ret=0
      ;;
      -E|--enable)
    _arguments \
      '*:useflags:_gentoo_packages useflag' && ret=0
      ;;
      -D|--disable)
    _arguments \
      '*:active useflags:_gentoo_packages active_useflag' && ret=0
    esac
  else
    _arguments \
      '*:useflag:_gentoo_packages useflag' && ret=0
  fi
}

_equery () {
  # Based off of X/_xauth.
  local state context line expl ret=1
  local tmp cmd start_args common_args

  start_args=(
    {'(--nocolor)-C','(-C)--nocolor'}'[turns off colors]'
    {'(--no-pipe)-N','(-N)--no-pipe'}'[turn off pipe detection]'
    {'(--quiet)-q','(-q)--quiet'}'[minimal output]'
    {'(--help)-h','(-h)--help'}'[show help]'
    {'(--version)-V','(-V)--version'}'[show version]'
  )

  common_args=(
    '(-I --exclude-installed)'{-I,--exclude-installed}'[do not search installed packages]'
    '(-p --portage-tree)'{-p,--portage-tree}'[also search in portage tree]'
    '(-o --overlay-tree)'{-o,--overlay-tree}'[also search in overlay tree]'
  )

  _arguments -s $start_args \
    '*::command:->command' && ret=0

  while [[ -n "$state" ]]; do
    tmp="$state"
    state=
    case "$tmp" in
      command)
        if (( CURRENT == 1 )); then
          state=subcommands
        else
          cmd="$words[1]"
          curcontext="${curcontext%:*:*}:equery-${cmd}:"
          case "$cmd" in
            belongs|b)
              _arguments \
                '(-e --early-out)'{-e,--early-out}'[stop when first match found]' \
                '(-f --full-regex)'{-f,--full-regex}'[supplied query is a regex]:pattern:' \
                '(-n --name-only)'{-n,--name-only}"[don't print the version]" \
                '*:file:_files' && ret=0
              ;;
            changes|c)
              _arguments \
                '(-l --latest)'{-l,--latest}'[only display latest ChangeLog entry]' \
                '(-f --full)'{-f,--full}'[display full ChangeLog entry]' \
                '--limit[limit the number of entries displayed (with --full)]:number:' \
                '--from[which version to display from]' \
                '--to[which version to display to]' \
                ':portage:_packages available' && ret=0
              ;;
            check|k)
              _arguments \
                '(-f --full-regex)'{-f,--full-regex}'[supplied query is a regex]:pattern:' \
                '(-o --only-failures)'{-o,--only-failures}'[only display packages that do not pass]' \
                ':portage:_packages installed' && ret=0
              ;;
            depends|d)
              _arguments \
                '(-a --all-packages)'{-a,--all-packages}'[search in all available packages (slow)]:all packages:->packages' \
                '(-D --indirect)'{-D,--indirect}'[search indirect dependencies (VERY slow)]' \
                '--depth[limit indirect dependency tree to specified depth]:number:' \
                '*:package:_packages installed' && ret=0
              ;;
            depgraph|g)
              _arguments \
                '(-A --no-atom)'{-A,--no-atom}'[do not show dependency atom]' \
                '(-M --no-mask)'{-M,--no-mask}'[do not show masking status]' \
                '(-U --no-useflags)'{-U,--no-useflags}'[do not show USE flags]' \
                '(-l --linear)'{-l,--linear}'[do not use fancy formatting]' \
                ':package:_packages installed' && ret=0
              ;;
            files|f)
              _arguments \
                '(-m --md5sum)'{-m,--md5sum}'[include MD5 sum in output]' \
                '(-s --timestamp)'{-s,--timestamp}'[include timestamp in output]' \
                '(-t --type)'{-t,--type}'[include file type in output]' \
                '--tree[display results in a tree (turns off other options)]' \
                '--filter=[filter output]:filter(s):_values -s , "" dir obj sym dev fifo path conf cmd doc man info' \
                ':installed pkgname:_packages installed' && ret=0
              ;;
            has|a)
              _arguments \
                $common_args \
                '(-F --format)'{-F,--format}'[a format template (see man page)]:format template' \
                ':KEY:' \
                ':VALUE:' && ret=0
              ;;
            hasuse|h)
              _arguments \
                $common_args \
                '(-F --format)'{-F,--format}'[specify a custom output format]:format template' \
                ':useflag:_gentoo_packages useflag' && ret=0
              ;;
            list|l)
              _arguments \
                $common_args \
                '(-d --duplicates)'{-d,--duplicates}'[list only installed duplicate packages]' \
                '(-b --binpkgs-missing)'{-b,--binpkgs-missing}'[list only installed packages without a corresponding binary package]' \
                '(-f --full-regex)'{-f,--full-regex}'[supplied query is a regex]:pattern:' \
                '(-m --mask-reason)'{-m,--mask-reason}'[include reason for package mask]' \
                '(-F --format)'{-F,--format}'[a format template (see man page)]:format template' \
                ': :_guard "^--*" pattern' && ret=0
              ;;
            meta|m)
              _arguments \
                '(-d --description)'{-d,--description}'[show an extended package description]' \
                '(-H --herd)'{-H,--herd}'[show the herd(s) for the package]' \
                '(-k --keywords)'{-k,--keywords}'[show keywords for all matching package versions]' \
                '(-l --license)'{-l,--license}'[show licenses for the best maching version]' \
                '(-m --maintainer)'{-m,--maintainer}'[show the maintainer(s) for the package]' \
                '(-S --stablreq)'{-S,--stablreq}'[show STABLEREQ arches (ccs) for all matching package versions]' \
                '(-u --useflags)'{-u,--useflags}'[show per-package USE flag descriptions]' \
                '(-U --upstream)'{-U,--upstream}'[show packages upstream information]' \
                '(-x --xml)'{-x,--xml}'[show the plain metadata.xml file]' \
                ':package:_packages available' && ret=0
              ;;
            size|s)
              _arguments \
                '(-b --bytes)'{-b,--bytes}'[report size in bytes]' \
                '(-f --full-regex)'{-f,--full-regex}'[supplied query is a regex]:pattern:' \
                ':package:_packages installed' && ret=0
              ;;
            uses|u)
              _arguments \
                '(-a --all)'{-a,--all}'[include non-installed packages]' \
                '(-i --ignore-linguas)'{-i,--ignore-linguas}"[don't show linguas USE flags]" \
                ":portage:_packages installed" && ret=0
              ;;
            which|w)
              _arguments \
                '(-m --include-masked)'{-m,--include-masked}'[return highest version ebuild available]' \
                '(-e --ebuild)'{-e,--ebuild}'[print the ebuild]' \
                ':portage:_packages available' && ret=0
              ;;
            *)
              _message 'command not found'
              ;;
          esac
        fi
        ;;
      subcommands)
        tmp=(
          {belongs,b}'[list all packages owning file(s)]'
          {check,k}'[check MD5sums and timestamps of package]'
          {changes,c}'[shows ChangeLog for specified package]'
          {depends,d}'[list all packages depending on specified package]'
          {depgraph,g}'[display a dependency tree for package]'
          {files,f}'[list files owned by package]'
          {hasuse,h}'[list all packages with specified useflag]'
          {list,l}'[list all packages matching pattern]'
          {size,s}'[print size of files contained in package]'
          {uses,u}'[display USE flags for package]'
          {which,w}'[print full path to ebuild for package]'
          {has,a}'[list all installed packages where specified KEY matches the specified VALUE]'
          {keywords,y}'[display keywords for specified PKG]'
          {meta,m}'[display metadata about PKG]'
        )
        _values 'equery command' $tmp && ret=0
        ;;
    esac
  done
}

_eclean_wrapper () {
  local global_opts pkg_opts dist_opts

  global_opts=(
    '(-C --nocolor)'{-C,--nocolor}'[turns off colors]'
    '(-d,--destructive)'{-d,--destructive}'[only keep the minimum for a reinstallation]'
    '(-e,--exclude-file)'{-e,--exclude-file}'[path to the exclusion file]:filename:_files'
    '(-i,--interactive)'{-i,--interactive}'[ask confirmation before deletions]'
    '(-n,--package-names)'{-n,--package-names}'[protect all versions (when --destructive)]'
    '(-p,--pretend)'{-p,--pretend}'[only display what would be cleaned]'
    '(-q,--quiet)'{-q,--quiet}'[minimal output]'
    '(-t,--time-limit)'{-t,--time-limit}'[don’t delete files modified since <time>]:time:_eclean_time'
    '(: -)'{-h,--help}'[show help]'
    '(: -)'{-V,--version}'[show version]'
  )

  dist_opts=(
    '(-s,--size-limit)'{-s,--size-limit}'[do not delete disfiles bigger than <size>]:size:_eclean_size'
    '(-f,--fetch-restricted)'{-f,--fetch-restricted}'[protect fetch-restricted files]'
  )

  # XXX: If you add options here make sure that it'll work.
  #       since there isn't any option *right* now, $pkg_opts
  #       is never used.
  pkg_opts=()

  # check which kind of eclean command we run.
  case "$words[1]" in
    eclean-pkg)
      _arguments -s $global_opts $pkg_opts && return 0
      ;;
    eclean-dist)
      _arguments -s $global_opts $dist_opts && return 0
      ;;
    eclean)
      # eclean. complete only specifics options if an action has been given,
      # global_opts and packages|distfiles otherwhise.
      if (( $words[(I)(packages)] )); then
        # Currently no options so return 0
        return 0
      elif (( $words[(I)(distfiles)] )); then
        _values "distfiles options" $dist_opts && return 0
      else
        _arguments -s $global_opts
        # complete packages|distfiles only if CURRENT-1 don't need an arg
        if [[ ! $words[CURRENT-1] =~ -(e|-exclude-file|t|-time-limit|s|-size-limit|h|-help|v|-version) ]]; then
          _values 'eclean command' \
            'packages[clean outdated binary packages]' \
            'distfiles[clean outdated packages sources files]' &&
            return 0
        fi
      fi
    ;;
  esac
}

_eclean_time () {
  # adapted from _chmod
  compset -P '*'
  suf=( -S '' )
  _alternative -O suf \
    'number:number:(0 1 2 3 4 5 6 7 8 9)' \
    'time_unit:time_unit:((y\:year m\:month w\:week d\:day h\:hour))' &&
    return 0
}

_eclean_size () {
  # adapted from _chmod
  compset -P '*'
  suf=( -S '' )
  _alternative -O suf \
    'number:number:(0 1 2 3 4 5 6 7 8 9)' \
    'time_unit:time_unit:((G\:gigabytes M\:megabytes K\:kilobytes B\:bytes))' &&
    return 0
}

_epkginfo () {
  _arguments -s \
    '(: -)'{-h,--help}'[Display help and exit]' \
    {'(--description)-d','(-d)--description'}'[show an extended package description]' \
    {'(--herd)-H','(-H)--herd'}'[show the herd(s) for the package]' \
    {'(--keywords)-k','(-k)--keywords'}'[show keywords for all matching package versions]' \
    {'(--license)-l','(-l)--license'}'[show licenses for the best maching version]' \
    {'(--maintainer)-m','(-m)--maintainer'}'[show the maintainer(s) for the package]' \
    {'(--stablreq)-S','(-S)--stablreq'}"[show STABLEREQ arches (cc's) for all matching package versions]" \
    {'(--useflags)-u','(-u)--useflags'}'[show per-package USE flag descriptions]' \
    {'(--upstream)-U','(-U)--upstream'}"[show package's upstream information]" \
    {'(--xml)-x','(-x)--xml'}'[show the plain metadata.xml file]' \
    '*:package:_gentoo_packages available'
}

_eshowkw () {
  _arguments -s \
    '(: -)'{-h,--help}'[Display help and exit]' \
    '(: -)'{-v,--version}'[Show package version and exit]' \
    {'(--arch)-a','(-a)--arch'}'[Display only specified arch(es)]:arch:_values -s , "arch" $(_gentoo_arches)' \
    {'(--align)-A','(-A)--align'}'[Specify alignment for descriptions (default: bottom)]:alignment:((top bottom))' \
    {'(--top-position)-T','(-T)--top-position'}'[Specify which fields we want to have in top listing (default: archlist)]:field:((archlist versionlist))' \
    {'(--bold)-B','(-B)--bold'}'[Print out each other column in bold for easier visual separation]' \
    {'(--color)-C','(-C)--color'}'[Force colored output]' \
    {'(--overlays)-O','(-O)--overlays'}'[Include overlays in search]' \
    {'(--prefix)-P','(-P)--prefix'}'[Display prefix keywords in output]' \
    {'(--ignore-slot)-S','(-S)--ignore-slot'}'[Treat slots as irelevant during detection of redundant packages]' \
    '*:package:_gentoo_packages available'
}

_genpkgindex () {
  _arguments -s \
    '(: -)'{-h,--help}'[Display help and exit]' \
    '(-h --help -q --quiet -v --verbose)'{-q,--quiet}'[Be quiet]' \
    '(-h --help -q --quiet -v --verbose)'{-v,--verbose}'[Be verbose]' \
    '(-h --help -c --compress)'{-c,--compress}'[Compresses the generated metadata with bzip2]' \
    '(-h --help -P --pkgdir)'{-P,--pkgdir}'[Set the base location of the binary packages (default $PKGDIR)]:file:_files'
}

_glsa-check () {
  local actions

  actions=(-l --list -d --dump --print -t --test -p --pretend -f --fix -i --inject -h --help -V --version -m --mail)

  _arguments -s \
    "($actions)"{-l,--list}'[list all unapplied GLSA]:glsa_id:_glsa_id' \
    "($actions)"{-d,--dump,--print}'[show all information about the given GLSA]:glsa_id:_glsa_id' \
    "($actions)"{-t,--test}'[test if this system is affected by the given GLSA]:glsa_id:_glsa_id' \
    "($actions)"{-p,--pretend}'[show the necessary commands to apply this GLSA]:glsa_id:_glsa_id' \
    "($actions)"{-f,--fix}'[try to auto-apply this GLSA (experimental)]:glsa_id:_glsa_id' \
    "($actions)"{-i,--inject}'[inject the given GLSA into the checkfile]:glsa_id:_glsa_id' \
    '(-n --nocolor)'{-n,--nocolor}'[disable colors (option)]' \
    '(: -)'{-h,--help}'[Show help message]' \
    '(: -)'{-V,--version}'[some information about this tool]' \
    '(-v --verbose)'{-v,--verbose}'[print more messages (option)]' \
    '(-c --cve)'{-c,--cve}'[show CAN ids in listing mode (option)]' \
    "($actions)"{-m,--mail}'[send a mail with the given GLSAs to the administrator]:glsa_id:_glsa_id'
}

# glsa-list can contain an arbitrary number of GLSA ids,
# filenames containing GLSAs or the special identifiers
# 'all', 'new' and 'affected'
_glsa_id () {
  # XXX: we'll avoid displaying GLSA ids, because the ratio use/noise
  # will be low. May be we should display only the X previous GLSA,
  # or GLSA ids of the X last month.
  #
  # start to look at ${EPREFIX}/usr/lib/gentoolkit/pym/glsa.py if GLSA_DIR is still
  # PORTDIR + "metadata/glsa/"
  # and then get the list (it's only xml files in GLSA_DIR, easy!)

  compadd 'all' 'new' 'affected'
  _files
}

_revdep-rebuild () {
  if (( $words[(I)(--)] )); then
  # here it's no more revdep-rebuild options, but emerge options that are called
  # FIXME: not working yet. need to load the _portage file
    _arguments -s '*:portage:_portage --emerge $@' && return 0
  fi

  _arguments -s \
    '(-C --nocolor)'{-C,--nocolor}'[Turn off colored output]' \
    '(-d --debug)'{-d,--debug}'[Print way too much information (uses bash set -xv)]' \
    '(-e --exact)'{-e,--exact}'[Emerge based on exact package version]' \
    '(: -)'{-h,--help}'[Print help]' \
    '(-i --ignore)'{-i,--ignore}'[Ignore temporary files from previous runs]' \
    '(-k --keep-temp)'{-k,--keep-temp}'[Do not delete temporary files on exit]' \
    '(-L --library)'{-L,--library}'[<NAME> Emerge existing packages that use the library with NAME]:file:_files' \
    '(-l --no-ld-path)'{-l,--no-ld-path}'[Do not set LD_LIBRARY_PATH]' \
    '(-o --no-order)'{-o,--no-order}'[Do not check the build order (Saves time, but may cause breakage)]' \
    '(-p --pretend)'{-p,--pretend}'[Do a trial run without actually emerging anything (also passed to emerge command)]' \
    '(-P --no-progress)'{-P,--no-progress}'[Turn off the progress meter]' \
    '(-q --quiet)'{-q,--quiet}'[Be less verbose (also passed to emerge command)]' \
    '(-v --verbose)'{-v,--verbose}'[Be more verbose (also passed to emerge command)]'
}

case "$service" in
  euse)
    _euse "$@" && return 0
    ;;
  equery)
    _equery "$@" && return 0
    ;;
  eclean*)
    _eclean_wrapper "$@" && return 0
    ;;
  epkginfo)
    _epkginfo "$@" && return 0
    ;;
  eshowkw)
    _eshowkw "$@" && return 0
    ;;
  genpkgindex)
    _genpkgindex "$@" && return 0
    ;;
  glsa-check)
    _glsa-check "$@" && return 0
    ;;
  revdep-rebuild)
    _revdep-rebuild "$@" && return 0
    ;;
esac

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