#compdef softwareupdate

_softwareupdate_ignored_update_name() {
  if [[ -z "$_softwareupdate_ignored_updates" ]]; then
    local res="$(_call_program pkgs softwareupdate --ignored)"
    _softwareupdate_ignored_updates=("${(Qs/, /)${${res#Current ignored updates: \(}%\)}}")
  fi
  if (( ${#_softwareupdate_ignored_updates} > 0 )); then
    _wanted pkgs expl "ignored package" compadd -a _softwareupdate_ignored_updates && return 0
  fi
  return 1
}

_softwareupdate_update_name() {
  local name line
  if [[ -z "$_softwareupdate_updates" ]]; then
    _softwareupdate_updates=()
    for line in ${(f)"$(_call_program pkgs softwareupdate --list)"}; do
      if [[ $line == '   '* ]]; then
        name="${line#   ? }"
      elif [[ -n "$name" ]]; then
        _softwareupdate_updates+=("$name:${line#	}")
        name=""
      fi
    done
  fi
  if (( ${#_softwareupdate_updates} > 0 )); then
    _describe -t pkgs "update name" _softwareupdate_updates && return 0
  fi
  return 1
}

_softwareupdate() {
  local context state line expl
  typeset -A opt_args

  _arguments -R \
    '(-h --help -l --list)-q[quiet mode]' \
    {-l,--list}'[list all available updates]:*:' \
    {-d,--download}'[download to directory set in InternetConfig]:*:' \
    {-i,--install}'[install (requires root)]:*: :->install' \
    '--ignored[show or manage ignored updates list (per-user)]:*:: :->ignored' \
    '--schedule[scheduler preferences (per-user)]:automatic checking:(on off)' \
    {-h,--help}'[print command usage]:*:' && return 0

  case "$state" in
    install)
      _arguments \
        '(* -a --all)'{-a,--all}'[all available active updates]' \
        '(* -r --req)'{-r,--req}'[all required active updates]' \
        '*:update name:_softwareupdate_update_name' && return 0
      ;;
    ignored)
      local -a ignored_subcmd
      ignored_subcmd=(add remove)

      if (( CURRENT == 1 )); then
        _describe -t commands "subcommands" ignored_subcmd && return 0
      fi
      case $words[1] in
        add)
          _softwareupdate_update_name && return 0
          ;;
        remove)
          _arguments \
            '(* -a --all)'{-a,--all}'[all available active updates]' \
            '*:update name:_softwareupdate_ignored_update_name' && return 0
          ;;
      esac
      ;;
  esac
  return 1
}

_softwareupdate "$@"
