#compdef kameleon

# This is ZSH completion script based on the kameleon 2.6.0.dev API
#
# Author: Michael Mercier
#
# This was made with the help of this howto:
# https://github.com/zsh-users/zsh-completions/blob/master/zsh-completions-howto.org
# and with the _git completion file

# Helpers
template_list="kameleon template list | tail -n +4 | cut -f1 -d'|'"

# Repository kameleon subcommands
_kameleon_repository () {
  local curcontext=$curcontext state line ret=1
  declare -A opt_args

  _arguments -C \
    ': :->command' \
    '*:: :->option-or-argument' && ret=0

  case $state in
    (command)
      declare -a commands

      commands=(
        add:'Adds a new named NAME repository at URL'
	      help:'Describe available subcommands or one specific subcommand'
	      list:'Lists available repositories'
        update:'Update specified repository')

      _describe -t commands command commands && ret=0
      ;;
    (option-or-argument)
      curcontext=${curcontext%:*}-$line[1]:

      case $line[1] in
        (add)
          _arguments \
            '1:Repository local name' \
            '2:Repository URL or local path:_urls' \
            '(-b --branch=)'{-b,--branch=}':To checkout BRANCH' && ret=0
          ;;
        (help)
          _arguments \
            '::Repository sub command:(add list update)' && ret=0
          ;;
        (update)
          _arguments \
            ":Update the repository named NAME:($(kameleon repository list))" && ret=0
          ;;
      esac
    esac
  return ret
}

# Template kameleon subcommands
_kameleon_template () {
  local curcontext=$curcontext state line ret=1
  declare -A opt_args

  _arguments -C \
    ': :->command' \
    '*:: :->option-or-argument' && ret=0

  case $state in
    (command)
      declare -a commands

      commands=(
	      help:'Describe available subcommands or one specific subcommand'
	      import:'Imports the given template'
	      info:'Display detailed information about a template'
	      list:'Lists available templates'
        repository:'alias for \"kameleon repository\"')

      _describe -t commands command commands && ret=0
      ;;
    (option-or-argument)
      curcontext=${curcontext%:*}-$line[1]:

      case $line[1] in
        (help)
          _arguments \
            '::Template sub command:(import info list repository)' && ret=0
          ;;
        (import)
          _arguments \
            ":template name:($(kameleon template list | tail -n +4 | cut -f1 -d'|'))" && ret=0
          ;;
        (info)
          _arguments \
            ":template name:($(kameleon template list | tail -n +4 | cut -f1 -d'|'))" && ret=0
            '*'{-g,--global}':Custom global variable define as key\:value' && ret=0
          ;;
        (repository)
          _kameleon_repository && ret=0
          ;;
      esac
    esac
  return ret
}
# TODO:
# - add checkpoint list completion
# - add key completion for global
# - factorize some options
# - allow common options everywere (not just befor command)

_kameleon () {
  local curcontext=$curcontext state line ret=1
  declare -A opt_args

  _arguments -C \
    '(--no-color)--color[Enables colorization in output (Default)]' \
    '(--color)--no-color[Disables colorization in output]' \
    '(--no-verbose --debug)--verbose[Enables verbose output for kameleon Users]' \
    '(--verbose)--no-verbose[Disables verbose output for kameleon Users (Default)]' \
    '(--no-debug)--debug[Enables debug output for kameleon Developpers]' \
    '(--debug --verbose)--no-debug[Disables debug output for kameleon Users and Developpers(Default)]' \
    '(--no-script)--script[Never prompts for User intervention]' \
    '(--script)--no-script[Prompts for user intervention if necessary (Default)]' \
    ': :->command' \
    '*:: :->option-or-argument' && ret=0

  case $state in
    (command)
      declare -a commands

      commands=(
        build:'Builds the appliance from the given recipe'
	      help:'Describe available commands or one specific command'
        info:'Display detailed information about a recipe'
	      list:'Lists all defined recipes in the current directory'
	      new:'Creates a new recipe'
	      repository:'Manages set of remote git repositories'
	      template:'Lists and imports templates'
	      version:'Prints the Kameleon version information')

      _describe -t commands command commands && ret=0
      ;;
    (option-or-argument)
      curcontext=${curcontext%:*}-$line[1]:

      case $line[1] in
        (build)
          _arguments -C \
            '(--from-cache)1:Kameleon recipe path:_files' \
            '(1)--from-cache=:Persistent cache tar file to build the image:_files' \
            '--cache-archive-compression=:Select the persistent cache compression:(gzip xz bz2)' \
            '(-b --build-path)'{-b,--build-path=}':Build directory path:_directories' \
            '--clean[Runs the command `kameleon clean` first]' \
            '--from-checkpoint=:Specify checkpoint to build the image' \
            '--enable-checkpoint[Enables checkpoint \[experimental\]]' \
            {--checkpoints,--list-checkpoints}'[Lists all availables checkpoints]' \
            '--enable-cache[Generates a persistent cache for the appliance]' \
            '--cache-path=:Cache directory path:_directories' \
            '--proxy=:Specifies the hostname and port number of the parent HTTP proxy define as host\:port' \
            '--proxy-credentials=:Specifies the username and password if the parent proxy requires authorisation define as username\:password' \
            '*'{-g,--global}':Custom global variable define as key\:value' && ret=0
          ;;
        (help)
          _arguments \
            ":Kameleon commands:($(kameleon commands))" && ret=0
          ;;
        (info)
          _arguments \
            '*'{-g,--global}':Custom global variable define as key\:value' \
            '(--from-cache)1:Kameleon recipe path:_files' \
            '(1)--from-cache=:Persistent cache tar file to get info from:_files' && ret=0
          ;;
        (list)
          _nothing
          ;;
        (new)
          _arguments \
            '1:Kameleon recipe path:_files' \
            '2:Template name:->template_name' && ret=0
            case "$state" in
              template_name)
                _alternative ":templates name:($(kameleon template list | tail -n +4 | cut -f1 -d'|'))"  && ret=0
              ;;
            esac
          ;;
        (repository)
          _kameleon_repository && ret=0
          ;;
        (template)
          _kameleon_template && ret=0
          ;;
        (*)
          _nothing
          ;;
      esac
      ;;
  esac

  return ret
}

_kameleon "$@"
