#!/usr/bin/env bash
#
# about Bash Completion
# =======================
#
# Bash completion support for the `about` command,
# generated by [picocli](http://picocli.info/) version 2.2.0.
#
# Installation
# ------------
#
# 1. Place this file in a `bash-completion.d` folder:
#
#   * /etc/bash-completion.d
#   * /usr/local/etc/bash-completion.d
#   * ~/bash-completion.d
#
# 2. Open a new bash console, and type `about [TAB][TAB]`
#
# Documentation
# -------------
# The script is called by bash whenever [TAB] or [TAB][TAB] is pressed after
# 'about (..)'. By reading entered command line parameters,
# it determines possible bash completions and writes them to the COMPREPLY variable.
# Bash then completes the user input if only one entry is listed in the variable or
# shows the options if more than one is listed in COMPREPLY.
#
# References
# ----------
# [1] http://stackoverflow.com/a/12495480/1440785
# [2] http://tiswww.case.edu/php/chet/bash/FAQ
# [3] https://www.gnu.org/software/bash/manual/html_node/The-Shopt-Builtin.html
# [4] https://stackoverflow.com/questions/17042057/bash-check-element-in-array-for-elements-in-another-array/17042655#17042655
# [5] https://www.gnu.org/software/bash/manual/html_node/Programmable-Completion.html#Programmable-Completion
#

# Enable programmable completion facilities (see [3])
shopt -s progcomp

# ArrContains takes two arguments, both of which are the name of arrays.
# It creates a temporary hash from lArr1 and then checks if all elements of lArr2
# are in the hashtable.
#
# Returns zero (no error) if all elements of the 2nd array are in the 1st array,
# otherwise returns 1 (error).
#
# Modified from [4]
function ArrContains() {
  local lArr1 lArr2
  declare -A tmp
  eval lArr1=("\"\${$1[@]}\"")
  eval lArr2=("\"\${$2[@]}\"")
  for i in "${lArr1[@]}";{ [ -n "$i" ] && ((++tmp[$i]));}
  for i in "${lArr2[@]}";{ [ -n "$i" ] && [ -z "${tmp[$i]}" ] && return 1;}
  return 0
}

# Bash completion entry point function.
# _complete_about finds which commands and subcommands have been specified
# on the command line and delegates to the appropriate function
# to generate possible options and subcommands for the last specified subcommand.
function _complete_about() {
  CMDS0=(infer)
  CMDS1=(transform)
  CMDS2=(validate)
  CMDS3=(infer maven)
  CMDS4=(infer npm)
  CMDS5=(infer github)

  ArrContains COMP_WORDS CMDS5 && { _picocli_about_infer_github; return $?; }
  ArrContains COMP_WORDS CMDS4 && { _picocli_about_infer_npm; return $?; }
  ArrContains COMP_WORDS CMDS3 && { _picocli_about_infer_maven; return $?; }
  ArrContains COMP_WORDS CMDS2 && { _picocli_about_validate; return $?; }
  ArrContains COMP_WORDS CMDS1 && { _picocli_about_transform; return $?; }
  ArrContains COMP_WORDS CMDS0 && { _picocli_about_infer; return $?; }

  # No subcommands were specified; generate completions for the top-level command.
  _picocli_about; return $?;
}

# Generates completions for the options and subcommands of the `about` command.
function _picocli_about() {
  # Get completion data
  CURR_WORD=${COMP_WORDS[COMP_CWORD]}
  PREV_WORD=${COMP_WORDS[COMP_CWORD-1]}

  COMMANDS="infer transform validate"
  FLAG_OPTS="-h --help"
  ARG_OPTS=""

  COMPREPLY=( $(compgen -W "${FLAG_OPTS} ${ARG_OPTS} ${COMMANDS}" -- ${CURR_WORD}) )
}

# Generates completions for the options and subcommands of the `infer` subcommand.
function _picocli_about_infer() {
  # Get completion data
  CURR_WORD=${COMP_WORDS[COMP_CWORD]}
  PREV_WORD=${COMP_WORDS[COMP_CWORD-1]}

  COMMANDS="maven npm github"
  FLAG_OPTS="-v --verbose -h --help"
  ARG_OPTS="-o --output"

  case ${CURR_WORD} in
    -o|--output)
      compopt -o filenames
      COMPREPLY=( $( compgen -f -- "" ) ) # files
      return $?
      ;;
    *)
      case ${PREV_WORD} in
        -o|--output)
          compopt -o filenames
          COMPREPLY=( $( compgen -f -- $CURR_WORD ) ) # files
          return $?
          ;;
      esac
  esac

  COMPREPLY=( $(compgen -W "${FLAG_OPTS} ${ARG_OPTS} ${COMMANDS}" -- ${CURR_WORD}) )
}

# Generates completions for the options and subcommands of the `transform` subcommand.
function _picocli_about_transform() {
  # Get completion data
  CURR_WORD=${COMP_WORDS[COMP_CWORD]}
  PREV_WORD=${COMP_WORDS[COMP_CWORD-1]}

  COMMANDS=""
  FLAG_OPTS="-v --verbose -h --help"
  ARG_OPTS="-i --input -o --output -f --targetFormat -d --dialect"
  targetFormat_OPTION_ARGS="JSON_LD TURTLE" # TransformTargetType values

  case ${CURR_WORD} in
    -i|--input)
      compopt -o filenames
      COMPREPLY=( $( compgen -f -- "" ) ) # files
      return $?
      ;;
    -o|--output)
      compopt -o filenames
      COMPREPLY=( $( compgen -f -- "" ) ) # files
      return $?
      ;;
    -f|--targetFormat)
      COMPREPLY=( $( compgen -W "${targetFormat_OPTION_ARGS}" -- "" ) )
      return $?
      ;;
    *)
      case ${PREV_WORD} in
        -i|--input)
          compopt -o filenames
          COMPREPLY=( $( compgen -f -- $CURR_WORD ) ) # files
          return $?
          ;;
        -o|--output)
          compopt -o filenames
          COMPREPLY=( $( compgen -f -- $CURR_WORD ) ) # files
          return $?
          ;;
        -f|--targetFormat)
          COMPREPLY=( $( compgen -W "${targetFormat_OPTION_ARGS}" -- $CURR_WORD ) )
          return $?
          ;;
      esac
  esac

  COMPREPLY=( $(compgen -W "${FLAG_OPTS} ${ARG_OPTS} ${COMMANDS}" -- ${CURR_WORD}) )
}

# Generates completions for the options and subcommands of the `validate` subcommand.
function _picocli_about_validate() {
  # Get completion data
  CURR_WORD=${COMP_WORDS[COMP_CWORD]}
  PREV_WORD=${COMP_WORDS[COMP_CWORD-1]}

  COMMANDS=""
  FLAG_OPTS="-v --verbose -h --help"
  ARG_OPTS="-i --input -n --profileName -p --profile -d --dialect"

  COMPREPLY=( $(compgen -W "${FLAG_OPTS} ${ARG_OPTS} ${COMMANDS}" -- ${CURR_WORD}) )
}

# Generates completions for the options and subcommands of the `maven` subcommand.
function _picocli_about_infer_maven() {
  # Get completion data
  CURR_WORD=${COMP_WORDS[COMP_CWORD]}
  PREV_WORD=${COMP_WORDS[COMP_CWORD-1]}

  COMMANDS=""
  FLAG_OPTS="-v --verbose -h --help"
  ARG_OPTS=""

  COMPREPLY=( $(compgen -W "${FLAG_OPTS} ${ARG_OPTS} ${COMMANDS}" -- ${CURR_WORD}) )
}

# Generates completions for the options and subcommands of the `npm` subcommand.
function _picocli_about_infer_npm() {
  # Get completion data
  CURR_WORD=${COMP_WORDS[COMP_CWORD]}
  PREV_WORD=${COMP_WORDS[COMP_CWORD-1]}

  COMMANDS=""
  FLAG_OPTS="-v --verbose -h --help"
  ARG_OPTS=""

  COMPREPLY=( $(compgen -W "${FLAG_OPTS} ${ARG_OPTS} ${COMMANDS}" -- ${CURR_WORD}) )
}

# Generates completions for the options and subcommands of the `github` subcommand.
function _picocli_about_infer_github() {
  # Get completion data
  CURR_WORD=${COMP_WORDS[COMP_CWORD]}
  PREV_WORD=${COMP_WORDS[COMP_CWORD-1]}

  COMMANDS=""
  FLAG_OPTS="-v --verbose -h --help"
  ARG_OPTS=""

  COMPREPLY=( $(compgen -W "${FLAG_OPTS} ${ARG_OPTS} ${COMMANDS}" -- ${CURR_WORD}) )
}

# Define a completion specification (a compspec) for the
# `about`, `about.sh`, and `about.bash` commands.
# Uses the bash `complete` builtin (see [5]) to specify that shell function
# `_complete_about` is responsible for generating possible completions for the
# current word on the command line.
# The `-o default` option means that if the function generated no matches, the
# default Bash completions and the Readline default filename completions are performed.
complete -F _complete_about -o default about about.sh about.bash

