#compdef cpio

(( $+_is_gnu )) || typeset -gA _is_gnu

local cmd=$service args ig curcontext="$curcontext" state line
local expl ret
local fmts='(bar bin odc newc crc tar ustar hpbin hpodc)'

if (( ! $+_is_gnu[$cmd] )); then
  if [[ $(_call_program version $cmd --version </dev/null 2>/dev/null) = *GNU* ]]
  then
    _is_gnu[$cmd]=yes
  else
    _is_gnu[$cmd]=
  fi
fi 
ig=$_is_gnu[$cmd]

if (( $CURRENT == 2 )); then
   # Complete arguments 
   args=('-o[create archive]' '-i[extract from archive]'
   '-p[run as filter on directory tree]')
   [[ -n $ig ]] && args=($args '--create[create archive]'
   '--extract[extract from archive]' 
   '--pass-through[run as filter on directory tree]'
   '--help[show help text]' '--version[show version information]')
else
  if [[ -n ${words[(r)(-o*|-[^-]*o*|--create)]} ]]; then
    # Optiona for creating archive
    if [[ -n $ig ]]; then
	args=(
	   '--file=:archive file:->afile'
	   "--format=:format type:$fmts"
	   '--message=:message at end of volume:'
	   '--null' '--reset-access-time'
	   '--verbose' '--dot' '--append' 
	   '--block-size=:block size in 512 byte units:'
	   '--dereference'
	   '--io-size=:block size in bytes'
	   '--quiet' '--force-local'  '--help'   '--version')
    fi
    args=($args
	  '-A[append files to archive]'
	  '-B[block size 5120 bytes with special file]'
	  '-C[set block size per record]:block size in bytes:(8192)'
	  '-F[set archive file to use]:archive file:->afile'
	  '(-H)-c[read/write header in ASCII]'
	  "(-c)-H[set format type for archive header]:$fmts"
	  '-L[follow symbolic links]'
	  '-M[print message at end of volume]:message to print:'
	  '-O[set output archive file]:output archive file:_files'
	 )
  elif [[ -n ${words[(r)(-i*|-[^-]*i*|--extract)]} ]]; then
    if [[ -n $ig ]]; then
      args=('--file=:archive file:->afile'
	    "--format=:format type:$fmts"
	    '--make-directories' '--nonmatching' 
            '--preserve-modification-time' '--numeric'
	    '--rename' '--list' '--swap-bytes' '--swap-halfwords'
	    '--dot' '--unconditional' '--verbose' 
	    '--block-size=:block size in 512 byte units:'
	    '--swap-halfwords'
	    '--io-size=:block size in bytes:'
	    '--pattern-file=:file with list of patterns:_files'
	    '--owner=:user (and group) for files:->user'  '--no-preserve-owner'
	    '--message=:message at end of volume:'
            '--force-local'
	    '--no-absolute-filenames' '--sparse' '--only-verify-crc'
	    '--quiet' '--help' '--version')
    fi
    args=($args
	  '-b[reverse bytes in word]'
	  '-B[block size 5120 bytes with special file]'
	  '-d[create directories as needed]'
	  '-C[set block size per record]:block size in bytes:(8192)'
	  '-E[read filenames from file]:file name for list of files:_files'
	  '-f[only copy files not matching patterns]'
	  '-F[set archive file to use]:archive file:->afile'
	  '(-H)-c[read/write header in ASCII]'
	  "(-c)-H[set format type for archive header]:$fmts"
	  '-I[set input archive file]:input archive file:_files'
	  '-m[preserve file modification times]'
	  '-M[print message at end of volume]:message to print:'
	  '-n[show UID and GID numerically]'
	  '-r[interactively rename files]'
	  '-R[set user and group for files]:user (and group) for files:->user'
	  '-s[swap bytes within each halfword]'
	  '-S[swap bytes within each word]'
	  '-t[print a table of contents]'
	  '*:pattern to extract'
	  )
  elif [[ -n ${words[(r)(-p*|-[^-]*p*|--pass-through)]} ]]; then
    if [[ -n $ig ]]; then
      args=('--null' '--reset-access-time' '--make-directories'
            '--link' '--quiet' '--preserve-modification-time'
	    '--unconditional' '--verbose' '--dot' '--dereference'
	    '--owner=:user (and group) for files:->user'
	    '--no-preserve-owner' '--sparse'  '--help'  '--version')
    fi
    args=($args
	  '-d[create directories as needed]'
	  '-l[link files instead of copying]'
	  '-L[follow symbolic links]'
	  '-m[preserve file modification times]'
	  '-R[set user and group for files]:user (and group) for files:->user'
	  '*:destination directory:_files -/'
	  )
  else
    return 1
  fi
  args=($args
	'-a[reset access time of input files]'
	)
fi 

ret=1
_arguments -C -s "$args[@]" && ret=0

if [[ $state = afile ]]; then
  if compset -P '*:'; then
    # TODO: doesn't need to be rsh.
    _wanted files expl 'remote files' \
       compadd $(rsh ${words[CURRENT]%:*} echo ${words[CURRENT]#*:}\*) && ret=0
  elif compset -P '*@'; then
    _wanted hosts expl 'remote host name' _hosts && ret=0
  else
    _alternative \
	'files:: _files' \
	'hosts:remote host name:_hosts -S:' \
	'users:user name:_users -qS@' && ret=0
  fi
elif [[ $state = user ]]; then
  if compset -P '*[:.]'; then
    _groups
  else
    local suf=.
    [[ $OSTYPE = (solaris|hpux)* ]] && suf=:
    compset -S '.*' && unset suf
    _users -S "$suf" -q
  fi
fi

return ret
