#compdef demoreel
# zsh completion for demoreel (DEMO-0056).
# Put this directory on $fpath before compinit runs, in ~/.zshrc:
#   fpath=(/path/to/demoreel/completions $fpath)
# or install the file as /usr/share/zsh/site-functions/_demoreel.

# The names of recordings still running, for `demoreel stop`. Asked of
# demoreel's own live_runs(), the test `stop` itself uses: every run leaves its
# state file behind, so the files alone would offer finished runs too. Never
# test the run's lock instead -- taking it, even for a moment, can make a run
# starting at that instant refuse to record.
_demoreel_running() {
  # $words has been narrowed to the subcommand's own words by now, so the
  # command's name comes from _demoreel, which saved it before that.
  local exe=${commands[$_demoreel_cmd]:-$_demoreel_cmd}
  local -a names
  names=(${(f)"$(python3 -c 'import importlib.machinery as m, importlib.util as u, sys
l = m.SourceFileLoader("demoreel", sys.argv[1])
d = u.module_from_spec(u.spec_from_loader("demoreel", l))
l.exec_module(d)
sys.stdout.write("".join(e["name"] + "\n" for e in d.live_runs()))' \
    $exe 2>/dev/null)"})
  _describe -t runs 'running recording' names
}

# A step is one quoted word, 'click 400 300': offer the verb, and let the user
# finish the step inside the quotes.
_demoreel_step() {
  local -a verbs=(wait move click type key hold drag)
  compset -P "['\"]"
  compadd -S ' ' -q -- $verbs
}

_demoreel() {
  local curcontext=$curcontext state line _demoreel_cmd=$words[1]
  local -a both
  both=(
    '(- *)'{-h,--help}'[show help]'
    '*'{-a+,--action=}'[scripted step, repeatable]:step:_demoreel_step'
    '(-a --action)--steps=[read the scripted steps from a file, - for stdin]:file:_files'
    '--app-log=[keep the app'\''s own output in a file]:file:_files'
    '--settle=[wait up to SECONDS for the first frame]:seconds:'
    '--gpu[for an app that needs the graphics card]'
    '--cursor[show the mouse pointer]'
    '--startup-timeout=[how long to wait for the app'\''s window]:seconds:'
    {-s+,--size=}'[virtual display size]:WxH:'
  )
  # The finishing commands: files in, a file out.
  local -a finish video fades
  finish=('(- *)'{-h,--help}'[show help]')
  video=({-o+,--output=}'[video file to write]:file:_files')
  fades=(
    '--fade-in=[start black]:seconds:'
    '--fade-out=[end on black]:seconds:'
  )
  music=(
    '--music=[lay this sound file under the film]:file:_files'
    '--music-level=[the level the music averages]:dB:'
    '--music-fade-in=[the music arrives over this long]:seconds:'
    '--music-fade-out=[the music goes over this long]:seconds:'
  )
  nosound=('--no-sound[leave out the videos'\'' own sound]')
  _arguments -C \
    '(- :)'{-h,--help}'[show help]' \
    '(- :)--version[show the version]' \
    '1:command:->command' \
    '*::argument:->argument'
  case $state in
    command)
      local -a cmds=(
        'record:record an app and write a video file'
        'shot:take one picture of an app and write a PNG'
        'check:test whether this machine can record, without recording'
        'stop:end a running recording early'
        'edit:make a film from a script of scenes'
        'trim:cut the start and the end off a video'
        'caption:put text over part of a video'
        'join:put videos end to end'
        'card:make a clip from a picture, or from text'
        'motion:report how smooth a video is and where it stands still'
        'poster:save one frame of a video as a picture'
      )
      _describe -t commands 'demoreel command' cmds ;;
    argument)
      curcontext=${curcontext%:*:*}:demoreel-$words[1]:
      # Everything after -- is the app's own command line, completed as if it
      # had been typed alone. Found by hand: _arguments -S gave a different
      # answer depending on whether an option came before the --.
      local dashes=${words[(i)--]}
      if [[ $words[1] == (record|shot) ]] && (( dashes < CURRENT )); then
        shift $dashes words
        (( CURRENT -= dashes ))
        _normal
        return
      fi
      case $words[1] in
        record)
          _arguments -S $both \
            {-o+,--output=}'[video file to write]:file:_files' \
            {-d+,--duration=}'[seconds to record; 0 means until stop]:seconds:' \
            {-r+,--framerate=}'[frames per second]:fps:' \
            {-n+,--name=}'[name for this run]:name:' \
            '--audio[put the app'\''s own sound in the video]' ;;
        shot)
          _arguments -S $both \
            {-o+,--output=}'[picture file to write]:file:_files' ;;
        check)
          _arguments '(-)'{-h,--help}'[show help]' ;;
        stop)
          _arguments '(-)'{-h,--help}'[show help]' \
            '1:running recording:_demoreel_running' ;;
        edit)
          _arguments -S $finish $video \
            {-s+,--size=}'[the film'\''s picture size]:WxH:' \
            {-r+,--framerate=}'[the film'\''s frames per second]:fps:' \
            '1:script:_files' ;;
        trim)
          _arguments -S $finish $video $fades $music $nosound \
            '--from=[where the kept part starts]:seconds:' \
            '--to=[the last moment kept]:seconds:' \
            '*--fade-at=[fade to black and back around this moment]:seconds:' \
            '--fade-length=[how long each half of a fade-at takes]:seconds:' \
            '1:video:_files' ;;
        caption)
          _arguments -S $finish $video $fades $music $nosound \
            '*--text=[one line of text, repeatable]:words:' \
            '*--from=[when the text before it appears]:seconds:' \
            '*--to=[when the text before it goes]:seconds:' \
            '*--text-size=[the height of the text before it]:percent:' \
            '1:video:_files' ;;
        join)
          _arguments -S $finish $video $fades $music $nosound \
            '--crossfade=[fade from each video into the next]:seconds:' \
            '*:video:_files' ;;
        card)
          _arguments -S $finish $video $fades $music \
            {-d+,--duration=}'[how many seconds the card lasts]:seconds:' \
            '--text=[one line of text]:words:' \
            '--text-size=[the height of the text]:percent:' \
            '--background=[the background colour]:#RRGGBB:' \
            '--like=[take the size and frame rate from this video]:video:_files' \
            {-s+,--size=}'[the picture size]:WxH:' \
            {-r+,--framerate=}'[frames per second]:fps:' \
            '1:picture:_files' ;;
        motion)
          _arguments -S $finish \
            '--from=[look from here]:seconds:' \
            '--to=[look up to here]:seconds:' \
            '--still=[report a stretch with no change longer than this]:seconds:' \
            '--json[print the report as one JSON object]' \
            '1:video:_files' ;;
        poster)
          _arguments -S $finish \
            {-o+,--output=}'[picture file to write]:file:_files' \
            {-t+,--time=}'[which moment to save]:seconds:' \
            '1:video:_files' ;;
      esac ;;
  esac
}

_demoreel "$@"
