#compdef pclean pconfig pebuild pinspect pmaint pmerge pquery psite pcd

SHELL_LIB=$(python -c 'from pkgcore import const; print(const.LIBDIR_PATH)')/shell/zsh/pkgcore.zsh
source "${SHELL_LIB}" || print "$0: failed to load '${SHELL_LIB}'" >&2
unset SHELL_LIB

common_main_args=(
  '(- :)'--version'[show version information and exit]'
  '--config[use config config or skip loading system config]:config path:_files'
  "--color[Color output]:yes/no:((y\:'yes' n\:'no'))"
)

common_output_args=(
  '(- :)'{-h,--help}'[show help information and exit]'
  '(--debug --help -h)--debug[enable debugging output]'
  '(--quiet -q --verbose -v)'{-q,--quiet}'[suppress non-error output]'
  '(--verbose -v --quiet -q)'{-v,--verbose}'[show verbose output]'
)

common_args=(
  $common_main_args
  $common_output_args
)

domain_common_args=(
  $common_args
  '--domain[domain to use for this operation]'
)

_pclean() {
  local curcontext=$curcontext state state_descr line ret=1
  typeset -A opt_args

  _arguments -C \
    $common_args \
    '(-): :->command' \
    '(-)*:: :->subcommand' \
    && ret=0

  case $state in
    (command)
      typeset -a subcommands

      subcommands=(
        dist:'remove distfiles'
        pkg:'remove binpkgs'
        tmp:'remove tmpdir entries'
      )

      _describe -t subcommands subcommand subcommands && ret=0

      ;;
    (subcommand)
      curcontext=${curcontext%:*}-$line[1]:
      typeset -a shared_opts file_opts repo_opts

      shared_opts=(
        {'(--pretend)-p','(-p)--pretend'}'[dry run without performing any changes]'
        {'(--exclude)-x','(-x)--exclude'}'[list of packages to exclude from removal]'
        {'(--exclude-file)-X','(-X)--exclude-file'}'[path to exclusion file]'
        '*:target:'
      )

      file_opts=(
        {'(--modified)-m','(-m)--modified'}'[skip files that have been modified since a given time]'
        {'(--size)-s','(-s)--size'}'[skip files bigger than a given size]'
      )

      repo_opts=(
        {'(--installed)-I','(-I)--installed'}'[skip files for packages that are currently installed]'
        {'(--fetch-restricted)-f','(-f)--fetch-restricted'}'[skip fetch-restricted files]'
      )

      pkg_opts=(
        '--source-repo[remove binpkgs with matching source repo]'
      )

      case $line[1] in
        (dist)
          _arguments -C -A '-*' \
            $domain_common_args \
            $shared_opts \
            $file_opts \
            $repo_opts \
            {'(--ignore-failures)-i','(-i)--ignore-failures'}'[ignore checksum parsing errors]' \
            && ret=0
          ;;
        (pkg)
          _arguments -C -A '-*' \
            $domain_common_args \
            $shared_opts \
            $file_opts \
            $repo_opts \
            $pkg_opts \
            && ret=0
          ;;
        (tmp)
          _arguments -C -A '-*' \
            $domain_common_args \
            $shared_opts \
            {'(--all)-a','(-a)--all'}'[wipe the entire tmpdir]' \
            && ret=0
          ;;
        (*)
          _nothing
          ;;
      esac
      ;;
  esac

  return ret
}

_pconfig() {
  local curcontext=$curcontext state state_descr line ret=1
  typeset -A opt_args

  _arguments -C \
    $common_args \
    '(-): :->command' \
    '(-)*:: :->subcommand' \
    && ret=0

  case $state in
    (command)
      typeset -a subcommands

      subcommands=(
        classes:'list all classes referenced by the config'
        describe_class:'describe the arguments a class needs, how to use it in a config'
        uncollapsable:'show configuration objects that could not be collapsed/instantiated'
        dump:'dump the entire configuration'
        configurables:'list registered configurables (may not be complete)'
        dump-uncollapsed:'dump the configuration in a raw, uncollapsed form'
        package:"invoke a package's custom configuration scripts"
        world:'inspect and modify the world file'
      )

      _describe -t subcommands subcommand subcommands && ret=0

      ;;
    (subcommand)
      curcontext=${curcontext%:*}-$line[1]:

      case $line[1] in
        (classes|uncollapsable|dump-uncollapsed)
          _arguments -C -A '-*' \
            $common_output_args \
            && ret=0
          ;;
        (describe_class)
          _arguments -C -A '-*' \
            $common_output_args \
            '*:classes' \
            && ret=0
          ;;
        (dump|configurables)
          _arguments -C -A '-*' \
            $common_output_args \
            '*:type' \
            && ret=0
          ;;
        (package)
          _arguments -C -A '-*' \
            $domain_common_args \
            '*:restriction or atom' \
            && ret=0
          ;;
        (world)
          _arguments -C -A '-*' \
            $domain_common_args \
            '(- :)'{-l,--list}'[list the current world file contents for this domain]' \
            '*'{-r,--remove}'[remove an entry from the world file]:package atom:' \
            '*'{-a,--add}'[add an entry to the world file]:package atom:' \
            && ret=0
          ;;
        (*)
          _nothing
          ;;
      esac
      ;;
  esac

  return ret
}

_pebuild() {
  local curcontext=$curcontext state state_descr line ret=1
  typeset -A opt_args

  _arguments -C \
    $domain_common_args \
    "--no-auto[run just the specified phases; it's up to the invoker to get the order right]" \
    '(-): :->atom-or-ebuild' \
    '(-)*:: :->phase' \
    && ret=0

  case $state in
    (atom-or-ebuild)
      # complete ebuilds before directories
      zstyle ':completion:*' file-patterns '*%p(^-/):other-files:ebuilds *(-/):directories:directories'

      _arguments \
        '*:ebuilds:_files -g \*.ebuild' \
        && ret=0
      ;;
    (phase)
      typeset -a phases

      phases=(
        setup:'run package specific setup actions or checks'
        unpack:'unpack all the sources to the workdir'
        prepare:'preparation of all sources such as applying patches'
        configure:'run configuration steps'
        compile:'run compilation steps'
        test:'run test steps'
        install:'install the package to the temp directory'
        clean:"remove the package's temporary directory"
      )

      _describe -V -t phases phase phases && ret=0
      ;;

    (*)
      _nothing
      ;;
  esac

  return ret
}

_pinspect() {
  local curcontext=$curcontext state state_descr line ret=1
  typeset -A opt_args

  _arguments -C \
    $common_args \
    '(-): :->command' \
    '(-)*:: :->subcommand' \
    && ret=0

  case $state in
    (command)
      typeset -a subcommands

      subcommands=(
        pkgsets:'pkgset related introspection'
        eapi_usage:'report of eapi usage for targeted repos'
        license_usage:'report of license usage for targeted repos'
        eclass_usage:'report of eclass usage for targeted repos'
        mirror_usage:'report of SRC_URI mirror usage for targeted repos'
        distfiles_usage:'report detailing distfiles space usage for targeted repos'
        query:'auxiliary access to ebuild/repository info via portageq akin API'
        portageq:'portageq compatible interface to query commands'
        profile:'profile related querying'
        digests:'identify what packages are missing digest info'
      )

      _describe -t subcommands subcommand subcommands && ret=0

      ;;
    (subcommand)
      curcontext=${curcontext%:*}-$line[1]:

      typeset -a historical_repo_data_opts
      historical_repo_data_opts=(
        '(- :)'{-h,--help}'[show help information and exit]'
        '--no-final-summary[disable outputting a summary of data across all repos]'
        '--sort-by-name[sort output by name, rather then by frequency]'
        '--first[show only the first N detail items]:number'
        '--last[show only the last N detail items]:number'
        '*:repo:_repos -t siab'
      )

      case $line[1] in
        (pkgsets)
          _arguments -C -A '-*' \
            '(- :)'{-h,--help}'[show help information and exit]' \
            '--all[display info on all pkgsets]' \
            ':pkgset:' \
            && ret=0
          ;;
        ((eapi|license|eclass|mirror)_usage)
          _arguments -C -A '-*' \
            $historical_repo_data_opts \
            && ret=0
          ;;
        (distfiles_usage)
          _arguments -C -A '-*' \
            '--no-repo-summary[disable outputting repo summaries]' \
            '--no-detail[disable outputting a detail view of all repos]' \
            '--include-nonmirrored[if set, nonmirrored distfiles will be included in the total]' \
            '--include-restricted[if set, fetch restricted distfiles will be included in the total]' \
            $historical_repo_data_opts \
            && ret=0
          ;;
        (query)
          _arguments -C \
            '(- :)'{-h,--help}'[show help information and exit]' \
            '(-): :->command' \
            '(-)*:: :->subcommand' \
            && ret=0

          case $state in
            (command)
              typeset -a subcommands

              subcommands=(
                best_version:'return the maximum visble version for a given atom'
                env_var:'return configuration defined variables'
                get_profiles:'show available profiles for a given repo'
                get_repo_path:'show repo path for a given repo'
                get_repos:'return list of configured repos'
                has_version:'return 0 if an atom is merged, 1 if not'
                mass_best_version:'multiple best_version calls'
              )

              _describe -t subcommands subcommand subcommands && ret=0
              ;;
            (subcommand)
              curcontext=${curcontext%:*}-$line[1]:

              typeset -a subcmd_opts
              query_subcmd_opts=(
                '(- :)'{-h,--help}'[show help information and exit]'
                '--eapi[limit all operations to just what the given EAPI supports]:EAPI'
                '--use[override the use flags used for transitive USE deps]:USE'
                '--domain[domain to use for this operation]:domain'
                '--domain-at-root[specify the domain to use via its root path]:root path:_path_files -/'
              )

              case $line[1] in
                (best_version|has_version|mass_best_version)
                  _arguments -C -A '-*' \
                    $subcmd_opts \
                    '*:package atom' \
                    && ret=0
                  ;;
                (env_var)
                  _arguments -C -A '-*' \
                    $subcmd_opts \
                    '*:variable' \
                    && ret=0
                  ;;
                (get_profiles|get_repo_path)
                  _arguments -C -A '-*' \
                    $subcmd_opts \
                    ':repo:_repos' \
                    && ret=0
                  ;;
                (get_repos)
                  _arguments -C -A '-*' \
                    $subcmd_opts \
                    && ret=0
                  ;;
                (*)
                  _nothing
                  ;;
               esac
               ;;
            (*)
              _nothing
              ;;
          esac
          ;;
        (portageq)
          _arguments -C \
            '(- :)'{-h,--help}'[show help information and exit]' \
            '(-): :->command' \
            '(-)*:: :->subcommand' \
            && ret=0

          case $state in
            (command)
              typeset -a subcommands

              subcommands=(
                best_version:'return the maximum visble version for a given atom'
                envvar:'return configuration defined variables (deprecated)'
                envvar2:'return configuration defined variables'
                get_repo_news_path:'show the news path for a given repo'
                get_repo_path:'show repo path for a given repo'
                get_repos:'return list of configured repos'
                has_version:'return 0 if an atom is merged, 1 if not'
                mass_best_version:'multiple best_version calls'
                match:'shorthand for `pquery --installed`'
              )

              _describe -t subcommands subcommand subcommands && ret=0
              ;;
            (subcommand)
              curcontext=${curcontext%:*}-$line[1]:

              typeset -a portageq_subcmd_opts
              subcmd_opts=(
                '(- :)'{-h,--help}'[show help information and exit]'
                '--eapi[limit all operations to just what the given EAPI supports]:EAPI'
                '--use[override the use flags used for transitive USE deps]:USE'
              )

              case $line[1] in
                (best_version|has_version|mass_best_version|match)
                  _arguments -C -A '-*' \
                    $subcmd_opts \
                    '1:root path:_path_files -/' \
                    '2:package atom' \
                    && ret=0
                  ;;
                (envvar|envvar2)
                  _arguments -C -A '-*' \
                    $subcmd_opts \
                    '1:root path:_path_files -/' \
                    '2:variable' \
                    && ret=0
                  ;;
                (get_repo_path|get_repo_news_path)
                  _arguments -C -A '-*' \
                    $subcmd_opts \
                    '1:root path:_path_files -/' \
                    '2:repo:_repos' \
                    && ret=0
                  ;;
                (get_repos)
                  _arguments -C -A '-*' \
                    $subcmd_opts \
                    && ret=0
                  ;;
                (*)
                  _nothing
                  ;;
               esac
               ;;
            (*)
              _nothing
              ;;
          esac
          ;;
        (profile)
          typeset -a profile_attrs
          local profile_opts='-f'

          profile_attrs=(
            parent:'output the linearized tree of inherited parents'
            eapi:'output EAPI support required for reading this profile'
            deprecated:'dump deprecation notices, if any'
            provided:'list all package.provided packages'
            system:'output the system package set'
            use_expand:'output the USE_EXPAND configuration for this profile'
            iuse_effective:'output the IUSE_EFFECTIVE value for this profile'
            masks:'inspect package masks'
            unmasks:'inspect package unmasks'
            bashrcs:'inspect bashrcs'
            keywords:'inspect package.keywords'
            accept_keywords:'inspect package.accept_keywords'
            use:'inspect package.use'
            masked_use:'inspect masked use flags'
            stable_masked_use:'inspect stable masked use flags'
            forced_use:'inspect forced use flags'
            stable_forced_use:'inspect stable forced use flags'
            defaults:'inspect defined configuration for this profile'
            arch:'output the arch defined for this profile'
            status:'output the status of this profile'
          )

          # only complete profiles from the specified repo
          if (( words[(I)-r|--repo] )); then
            local repo=${words[(( $words[(I)-r|--repo] + 1 ))]}
            profile_opts="-r ${repo}"
          fi

          _arguments -C -A '-*' \
            '(- :)'{-h,--help}'[show help information and exit]' \
            {'(--repo)-r','(-r)--repo'}'[target repository]:repo:_repos' \
            '1:profile attribute:(($profile_attrs))' \
            "2:profile:_profiles ${profile_opts}" \
            && ret=0
          ;;
        (digests)
          _arguments -C -A '-*' \
            '(- :)'{-h,--help}'[show help information and exit]' \
            ':repo:_repos' \
            && ret=0
          ;;
        (*)
          _nothing
          ;;
      esac
      ;;
  esac
  return ret
}

_pmaint() {
  local curcontext=$curcontext state state_descr line ret=1
  typeset -A opt_args

  _arguments -C \
    $common_args \
    '(-): :->command' \
    '(-)*:: :->subcommand' \
    && ret=0

  case $state in
    (command)
      typeset -a subcommands

      subcommands=(
        sync:'synchronize a local repository with its defined remote'
        copy:'copy binpkgs between repositories; primarily useful for quickpkging a livefs pkg'
        regen:'regenerate repository caches'
        env-update:'update env.d and ldconfig'
        mirror:'mirror the sources for a package in full'
      )

      _describe -t subcommands subcommand subcommands && ret=0
      ;;
    (subcommand)
      curcontext=${curcontext%:*}-$line[1]:

      case $line[1] in
        (sync)
          _arguments -C -w -S -s -A '-*' \
            $common_output_args \
            '*:repo:_repos' \
            && ret=0
          ;;
        (copy)
          _arguments -C -w -S -s -A '-*' \
            $common_output_args \
            {'(--source-repo)-s','(-s)--source-repo'}'[copy strictly from the supplied repository]:repo:_repos' \
            {'(--ignore-missing)-i','(-i)--ignore-missing'}"[if a matching pkg already exists in the target, don't update it]" \
            ':target repo:_repos' \
            ':query:' \
            && ret=0
          ;;
        (regen)
          _arguments -C -w -S -s -A '-*' \
            $common_output_args \
            '--disable-eclass-caching[disable caching eclasses into functions (results in a ~2x slower regen process, only disable when debugging)]' \
            {'(--threads)-t','(-t)--threads'}'[number of threads to use for regeneration (defaults to using all available processors]:number' \
            '--force[force regeneration to occur regardless of staleness checks]' \
            '--rsync[update timestamps for rsync repos]' \
            '--use-local-desc[update local USE flag description cache (profiles/use.local.desc)]' \
            '--pkg-desc-index[update package description cache (metadata/pkg_desc_index)]' \
            '*:repo:_repos' \
            && ret=0
          ;;
        (env-update)
          _arguments -C -w -S -s -A '-*' \
            $common_output_args \
            '--skip-ldconfig[do not update etc/ldso.conf and ld.so.cache]' \
            && ret=0
          ;;
        (mirror)
          _arguments -C -w -S -s -A '-*' \
            $common_output_args \
            {'(--ignore-failures)-f','(-f)--ignore-failures'}'[if a failure occurs, keep going]' \
            ':query:' \
            && ret=0
          ;;
        (*)
          _nothing
          ;;
      esac
      ;;
  esac

  return ret
}

_pmerge() {
  local curcontext=$curcontext state state_descr line ret=1
  typeset -A opt_args
  typeset -a pkg ops resolver output

  pkg=(
    {'(--newuse)-N','(-N)--newuse'}'[check for changed useflags in installed packages (implies -1)]'
  )

  ops=(
    {'(--unmerge)-C','(-C)--unmerge'}'[unmerge a package]'
    '--clean[remove installed packages not referenced by any target packages/sets]'
    {'(--pretend)-p','(-p)--pretend'}"[do the resolution, but don't merge/fetch anything]"
    '--ignore-failures[ignore failures while running all types of tasks]'
    {'(--ask)-a','(-a)--ask'}'[do the resolution, but ask to merge/fetch anything]'
    "--force[force merging to a repo, regardless of if it's frozen]"
    {'(--fetchonly)-f','(-f)--fetchonly'}'[do only the fetch steps of the resolved plan]'
    {'(--oneshot)-1','(-1)--oneshot'}'[do not record changes in the world file]'
  )

  resolver=(
    {'(--upgrade)-u','(-u)--upgrade'}'[try to upgrade already installed packages/dependencies]'
    {'(--downgrade)-d','(-d)--downgrade'}'[try to downgrade already installed packages/dependencies]'
    {'(--deep)-D','(-D)--deep'}'[force the resolver to verify already installed dependencies]'
    '--preload-vdb-state[enable preloading of the installed packages database]'
    {'(--ignore-cycles)-i','(-i)--ignore-cycles'}"[ignore cycles if they're found to be unbreakable]"
    "--with-bdeps[process build dependencies for built packages (by default they're ignored]"
    {'(--nodeps)-O','(-O)--nodeps'}'[disable dependency resolution]'
    {'(--noreplace)-n','(-n)--noreplace'}"[don't reinstall target atoms if they're already installed]"
    {'(--buildpkg)-b','(-b)--buildpkg'}'[build binpkgs]'
    {'(--usepkg)-k','(-k)--usepkg'}'[prefer to use binpkgs]'
    {'(--usepkgonly)-K','(-K)--usepkgonly'}'[use only binpkgs]'
    {'(--source-only)-S','(-S)--source-only'}'[use only source packages, no binpkgs]'
    {'(--empty)-e','(-e)--empty'}'[force rebuilding of all involved packages]'
  )

  output=(
    "--quiet-repo-display[use numbers to indicate repos instead of ::repo output in the package merge list]"
    {'(--formatter)-F','(-F)--formatter'}'[output formatter to use]:formatter:((basic pkgcore portage portage-verbose))'
  )

  _arguments -C -w -S -s -A '-*' \
    $domain_common_args \
    $pkg \
    $ops \
    $resolver \
    $output \
    '*:target:' \
    && ret=0

  return ret
}

_pquery() {
  local curcontext=$curcontext state state_descr line ret=1
  typeset -A opt_args
  typeset -a repo pkg output

  repo=(
    '--raw[disable configuration and filtering]'
    '--no-filters[disable all license filtering and visibility filtering]'
    "--virtuals[specific virtuals handling (everything is matched by default)]:options:((only\:'only match virtuals' disable\:'no matching virtuals'))"
    {'(--repo)-r','(-r)--repo'}'[target repository]:repo:_repos -t seib'
    {'(--ebuild-repos)-E','(-E)--ebuild-repos'}'[search all ebuild repos]'
    {'(--binary-repos)-B','(-B)--binary-repos'}'[search all binary repos]'
    {'(--installed)-I','(-I)--installed'}'[search installed pkgs]'
    {'(--all-repos)-A','(-A)--all-repos'}'[search all repos including the vdb]'
  )

  pkg=(
    '--all[match all packages (equivalent to "pquery *")]'
    '--has-use[exact string match on a USE flag]:use flag:_use -o'
    '--license[exact match on a license]:license:_licenses'
    '--revdep[shorthand for --restrict-revdep atom --print-revdep atom]:pkg atom:'
    '--revdep-pkgs[shorthand for --restrict-revdep-pkgs atom --print-revdep atom]:pkg atom:'
    '--restrict-revdep[dependency on an atom]:pkg atom:'
    '--restrict-revdep-pkgs[dependency on pkgs that match a specific atom]:pkg atom:'
    {'(--description)-S','(-S)--description'}'[regexp search on description and longdescription]:description regex'
    '--eapi[match packages using a given EAPI]'
    '--owns[exact match on an owned file/dir]:path:_files'
    '--owns-re[like "owns" but using a regexp for matching]:path regex:_files'
    '--maintainer[comma-separated list of regexes to search for maintainers]'
    '--maintainer-name[comma-separated list of maintainer name regexes to search for]'
    '--maintainer-email[comma-separated list of maintainer email regexes to search for]'
    '--maintainer-needed[match packages without a maintainer]'
    '--environment[regexp search in environment.bz2]'
    '--pkgset[find packages that match the given package set]'
    {'(--upgrade)-u','(-u)--upgrade'}'[matched installed packages without best slotted version]'
  )

  output=(
    {'(--first)-1','(-1)--first'}'[stop when first match is found]'
    {'(--no-version)-n','(-n)--no-version'}'[collapse multiple matching versions together]'
    '--min[show only the lowest version for each package]'
    '--max[show only the highest version for each package]'
    '--cpv[print the category/package-version]'
    {'(--atom)-a','(-a)--atom'}'[print =cat/pkg-3 instead of cat/pkg-3 (implies --cpv, has no effect with --no-version)]'
    "--attr[print this attribute's value (can be specified more than once)]"
    '--force-attr[like --attr but accepts any string as attribute name instead of only explicitly supported names]'
    '--one-attr[print one attribute, suppresses other output]'
    '--force-one-attr[like --one-attr but accepts any string as attribute name instead of only explicitly supported names]'
    '--one-attr[print one attribute, suppresses other output]'
    '--size[display size of all files owned by the package]'
    '--contents[list files owned by the package]'
    '--highlight-dep[highlight dependencies matching this atom]'
    '--blame[shorthand for --attr maintainers]'
    '--print-revdep[print what condition(s) trigger a dep]'
  )

  _arguments -C \
    $domain_common_args \
    $repo \
    $pkg \
    $output \
    '*:target:' \
    && ret=0

  return ret
}

_pcd() {
  local curcontext=$curcontext state state_descr line ret=1
  typeset -A opt_args

  _arguments -C \
    '(- :)'{-h,--help}'[show help information and exit]' \
    '1:package atom' \
    '2:repo:_repos -t sib' \
    && ret=0

  return ret
}

_psite() {
  local curcontext=$curcontext state state_descr line ret=1
  typeset -A opt_args

  _arguments -C \
    '(- :)'{-h,--help}'[show help information and exit]' \
    '1:package atom' \
    '2:repo:_repos -t sib' \
    && ret=0

  return ret
}

_pkgcore() {
  local ret=1
  _call_function ret _$service
  return ret
}

_pkgcore

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