#!/usr/bin/env bash
#
# filebot Bash Completion
# =======================
#
# Bash completion support for the `filebot` command,
# generated by [picocli](http://picocli.info/) version 4.6.3, modified by rednoah.
#
# Installation
# ------------
#
# 1. Source all completion scripts in your .bash_profile
#
#   cd $YOUR_APP_HOME/bin
#   for f in $(find . -name "*_completion"); do line=". $(pwd)/$f"; grep "$line" ~/.bash_profile || echo "$line" >> ~/.bash_profile; done
#
# 2. Open a new bash console, and type `filebot [TAB][TAB]`
#
# 1a. Alternatively, if you have [bash-completion](https://github.com/scop/bash-completion) installed:
#     Place this file in a `bash-completion.d` folder:
#
#   * /etc/bash-completion.d
#   * /usr/local/etc/bash-completion.d
#   * ~/bash-completion.d
#
# Documentation
# -------------
# The script is called by bash whenever [TAB] or [TAB][TAB] is pressed after
# 'filebot (..)'. 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] http://zsh.sourceforge.net/Doc/Release/Options.html#index-COMPLETE_005fALIASES
# [5] https://stackoverflow.com/questions/17042057/bash-check-element-in-array-for-elements-in-another-array/17042655#17042655
# [6] https://www.gnu.org/software/bash/manual/html_node/Programmable-Completion.html#Programmable-Completion
# [7] https://stackoverflow.com/questions/3249432/can-a-bash-tab-completion-script-be-used-in-zsh/27853970#27853970
#

if [ -n "$BASH_VERSION" ]; then
  # Enable programmable completion facilities when using bash (see [3])
  shopt -s progcomp
elif [ -n "$ZSH_VERSION" ]; then
  # Make alias a distinct command for completion purposes when using zsh (see [4])
  setopt COMPLETE_ALIASES
  alias compopt=complete

  # Enable bash completion in zsh (see [7])
  # Only initialize completions module once to avoid unregistering existing completions.
  if ! type compdef > /dev/null; then
    autoload -U +X compinit && compinit
  fi
  autoload -U +X bashcompinit && bashcompinit
fi

# CompWordsContainsArray takes an array and then checks
# if all elements of this array are in the global COMP_WORDS array.
#
# Returns zero (no error) if all elements of the array are in the COMP_WORDS array,
# otherwise returns 1 (error).
function CompWordsContainsArray() {
  declare -a localArray
  localArray=("$@")
  local findme
  for findme in "${localArray[@]}"; do
    if ElementNotInCompWords "$findme"; then return 1; fi
  done
  return 0
}
function ElementNotInCompWords() {
  local findme="$1"
  local element
  for element in "${COMP_WORDS[@]}"; do
    if [[ "$findme" = "$element" ]]; then return 1; fi
  done
  return 0
}

# The `currentPositionalIndex` function calculates the index of the current positional parameter.
#
# currentPositionalIndex takes three parameters:
# the command name,
# a space-separated string with the names of options that take a parameter, and
# a space-separated string with the names of boolean options (that don't take any params).
# When done, this function echos the current positional index to std_out.
#
# Example usage:
# local currIndex=$(currentPositionalIndex "mysubcommand" "$ARG_OPTS" "$FLAG_OPTS")
function currentPositionalIndex() {
  local commandName="$1"
  local optionsWithArgs="$2"
  local booleanOptions="$3"
  local previousWord
  local result=0

  for i in $(seq $((COMP_CWORD - 1)) -1 0); do
    previousWord=${COMP_WORDS[i]}
    if [ "${previousWord}" = "$commandName" ]; then
      break
    fi
    if [[ "${optionsWithArgs}" =~ ${previousWord} ]]; then
      ((result-=2)) # Arg option and its value not counted as positional param
    elif [[ "${booleanOptions}" =~ ${previousWord} ]]; then
      ((result-=1)) # Flag option itself not counted as positional param
    fi
    ((result++))
  done
  echo "$result"
}

# Bash completion entry point function.
# _complete_filebot 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_filebot() {
  # Edge case: if command line has no space after subcommand, then don't assume this subcommand is selected (remkop/picocli#1468).

  # Find the longest sequence of subcommands and call the bash function for that subcommand.


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

# Generates completions for the options and subcommands of the `filebot` command.
function _picocli_filebot() {
  # Get completion data
  local curr_word=${COMP_WORDS[COMP_CWORD]}
  local prev_word=${COMP_WORDS[COMP_CWORD-1]}

  local commands=""
  local flag_opts="-rename -non-strict -get-subtitles -check -list -find -mediainfo -revert -extract -r -d -unixfs -no-xattr -no-probe -no-index -no-history -clear-cache -clear-prefs -clear-history -version -help"
  local arg_opts="--mode --db --order --action --conflict --filter --mapper --format --lang --output --encoding -script --def --q --file-filter --file-order --apply -exec --log --log-file --license"
  local mode_option_args="interactive" # --mode values
  local db_option_args="TheMovieDB::TV AniDB TheTVDB TVmaze TheMovieDB OMDb AcoustID ID3 exif xattr file" # --db values
  local order_option_args="Airdate DVD Absolute Digital Story Production Date" # --order values
  local action_option_args="move copy keeplink symlink hardlink clone duplicate test" # --action values
  local conflict_option_args="skip replace auto index fail" # --conflict values
  local lang_option_args="af sq ar hy bg ca hr cs da nl en et fi fr qc de el he hi hu is id it ja x-jat ko lv lt mk ms zh tw hk no fa pl pt pb ro ru sr sk sl es mx sv th tr uk vi" # --lang values
  local encoding_option_args="UTF-8 Windows-1252" # --encoding values
  local StringString_option_args="name=value" # --def values
  local apply_option_args="artwork cover nfo url metadata import srt subtitles finder tags date chmod touch thumbnail reveal prune clean refresh" # --apply values
  local log_option_args="OFF SEVERE WARNING INFO CONFIG FINE FINER FINEST ALL" # --log values

  type compopt &>/dev/null && compopt +o default

  case ${prev_word} in
    --mode)
      COMPREPLY=( $( compgen -W "${mode_option_args}" -- "${curr_word}" ) )
      return $?
      ;;
    --db)
      COMPREPLY=( $( compgen -W "${db_option_args}" -- "${curr_word}" ) )
      return $?
      ;;
    --order)
      COMPREPLY=( $( compgen -W "${order_option_args}" -- "${curr_word}" ) )
      return $?
      ;;
    --action)
      COMPREPLY=( $( compgen -W "${action_option_args}" -- "${curr_word}" ) )
      return $?
      ;;
    --conflict)
      COMPREPLY=( $( compgen -W "${conflict_option_args}" -- "${curr_word}" ) )
      return $?
      ;;
    --filter)
      local IFS=$'\n'
      type compopt &>/dev/null && compopt -o filenames
      COMPREPLY=( $( compgen -X '!*.groovy' -f -- ${curr_word} ) ) # *.groovy files
      return $?
      ;;
    --mapper)
      local IFS=$'\n'
      type compopt &>/dev/null && compopt -o filenames
      COMPREPLY=( $( compgen -X '!*.groovy' -f -- ${curr_word} ) ) # *.groovy files
      return $?
      ;;
    --format)
      local IFS=$'\n'
      type compopt &>/dev/null && compopt -o filenames
      COMPREPLY=( $( compgen -X '!*.groovy' -f -- ${curr_word} ) ) # *.groovy files
      return $?
      ;;
    --lang)
      COMPREPLY=( $( compgen -W "${lang_option_args}" -- "${curr_word}" ) )
      return $?
      ;;
    --output)
      local IFS=$'\n'
      type compopt &>/dev/null && compopt -o dirnames
      COMPREPLY=( $( compgen -d -- ${curr_word} ) ) # directories
      return $?
      ;;
    --encoding)
      COMPREPLY=( $( compgen -W "${encoding_option_args}" -- "${curr_word}" ) )
      return $?
      ;;
    -script)
      local IFS=$'\n'
      type compopt &>/dev/null && compopt -o filenames
      COMPREPLY=( $( compgen -X '!*.groovy' -f -- ${curr_word} ) ) # *.groovy files
      return $?
      ;;
    --def)
      COMPREPLY=( $( compgen -W "${StringString_option_args}" -- "${curr_word}" ) )
      return $?
      ;;
    --q)
      local IFS=$'\n'
      type compopt &>/dev/null && compopt -o filenames
      COMPREPLY=( $( compgen -X '!*.groovy' -f -- ${curr_word} ) ) # *.groovy files
      return $?
      ;;
    --file-filter)
      local IFS=$'\n'
      type compopt &>/dev/null && compopt -o filenames
      COMPREPLY=( $( compgen -X '!*.groovy' -f -- ${curr_word} ) ) # *.groovy files
      return $?
      ;;
    --file-order)
      local IFS=$'\n'
      type compopt &>/dev/null && compopt -o filenames
      COMPREPLY=( $( compgen -X '!*.groovy' -f -- ${curr_word} ) ) # *.groovy files
      return $?
      ;;
    --apply)
      COMPREPLY=( $( compgen -W "${apply_option_args}" -- "${curr_word}" ) )
      return $?
      ;;
    -exec)
      COMPREPLY=( $( compgen -c -- ${curr_word} ) ) # commands
      return
      ;;
    --log)
      COMPREPLY=( $( compgen -W "${log_option_args}" -- "${curr_word}" ) )
      return $?
      ;;
    --log-file)
      local IFS=$'\n'
      type compopt &>/dev/null && compopt -o filenames
      COMPREPLY=( $( compgen -f -- "${curr_word}" ) ) # files
      return $?
      ;;
    --license)
      local IFS=$'\n'
      type compopt &>/dev/null && compopt -o filenames
      COMPREPLY=( $( compgen -X '!*.psm' -f -- ${curr_word} ) ) # *.psm files
      return $?
      ;;
  esac

  if [[ "${curr_word}" == -* ]]; then
    COMPREPLY=( $(compgen -W "${flag_opts} ${arg_opts}" -- "${curr_word}") )
    return $?
  fi

  # complete file arguments
  local IFS=$'\n'
  type compopt &>/dev/null && compopt -o filenames
  COMPREPLY=( $( compgen -f -- "${curr_word}" ) ) # files
  return $?
}

# Define a completion specification (a compspec) for the
# `filebot`, `filebot.sh`, and `filebot.bash` commands.
# Uses the bash `complete` builtin (see [6]) to specify that shell function
# `_complete_filebot` 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_filebot -o default filebot filebot.sh filebot.bash
