#compdef mssh
# ------------------------------------------------------------------------------
# Copyright (c) 2020 Hyeon Kim
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
# OTHER DEALINGS IN THE SOFTWARE.
# ------------------------------------------------------------------------------
# Description
# -----------
# mssh is a Python client for accessing EC2 instances via AWS EC2 Instance
# Connect.
#
# References:
#   https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-connect-methods.html#ec2-instance-connect-connecting-ec2-cli
#   https://github.com/aws/aws-ec2-instance-connect-cli
#   https://pypi.org/project/ec2instanceconnectcli/
#
# ------------------------------------------------------------------------------
# Authors
# -------
#
#  * Hyeon Kim (https://hyeon.me/)
#
# ------------------------------------------------------------------------------

# Do nothing if there's no AWS CLI
if (( ! $+commands[aws] )); then
  return
fi

# Define function only when it doesn't exist
(( $+functions[_mssh_cache_policy] )) || _mssh_cache_policy() {
  # Cache invalidates after 30 seconds
  #
  # Reference:
  #   https://zsh.sourceforge.net/Doc/Release/Expansion.html#index-globbing_002c-qualifiers
  local -a oldp
  oldp=( "$1"(ms+30) )
  (( $#oldp ))
}

# Unless user explicitly turned off caching, enable caching just for this context
local existing_setting
zstyle -s ":completion:${curcontext}:" use-cache existing_setting
if [[ -z "${existing_setting}" ]]; then
  zstyle ":completion:${curcontext}:" use-cache on
fi

# Update cache policy only when there was no existing policy
local existing_policy
zstyle -s ":completion:${curcontext}:" cache-policy existing_policy
if [[ -z "${existing_policy}" ]]; then
  zstyle ":completion:${curcontext}:" cache-policy _mssh_cache_policy
fi

local -a instances
if _cache_invalid mssh_instances || ! _retrieve_cache mssh_instances; then
  # Cache is invalid or caching retrieval failed (usually due to disabled cache)

  # Store the output of the AWS CLI separately
  #
  # Reference:
  #   https://unix.stackexchange.com/a/430182
  local stderr
  local -i exit_code
  () {
    aws ec2 describe-instances \
      --query 'Reservations[].Instances[] | [?State.Name == `running`].join(`:`, [InstanceId, Tags[?Key == `Name`].Value | [0]])' \
      --output text \
      >${1} 2>${2}
    exit_code=${?}
    IFS=$'\n\t' instances=($(<${1}))
    stderr=$(<${2})
  } =(:) =(:)

  if (( $exit_code == 0 )); then
    # AWS CLI successfully executed
    _store_cache mssh_instances instances
  else
    # AWS CLI failed, abort autocompletion
    _message -r "\
Failed autocomplete due to following reason:
${stderr}"
    return
  fi
fi

_describe 'command' instances

# Reference:
#   https://zsh.sourceforge.net/Doc/Release/Completion-System.html
#   https://github.com/zsh-users/zsh-completions/blob/master/zsh-completions-howto.org
