#!/usr/bin/env bash

set -o pipefail
if [[ "${ASDF_DEBUG}" == "1" ]]; then
  set -x
fi

# shellcheck source=lib/utils.bash
. "$(dirname "$(dirname "$0")")/lib/utils.bash"

find_cmd() {
  local cmd_dir="$1"
  shift

  local cmd_name
  local args_offset="$#"
  cmd_name="command-$(tr ' ' '-' <<<"${@:1:${args_offset}}").bash"
  while [ ! -f "$cmd_dir/$cmd_name" ] && [ "$args_offset" -gt 0 ]; do
    args_offset=$((args_offset - 1))
    cmd_name="command-$(tr ' ' '-' <<<"${@:1:${args_offset}}").bash"
  done

  if [ -f "$cmd_dir/$cmd_name" ]; then
    printf "%s %s\n" "$cmd_dir/$cmd_name" "$((args_offset + 1))"
  elif [ -f "$cmd_dir/command.bash" ]; then
    printf "%s %s\n" "$cmd_dir/command.bash" 1
  fi
}

find_asdf_cmd() {
  local asdf_cmd_dir
  asdf_cmd_dir="$(asdf_dir)/lib/commands"
  case "$1" in
  'exec' | 'current' | 'env' | 'global' | 'install' | 'latest' | 'local' | \
    'reshim' | 'uninstall' | 'update' | 'where' | 'which' | \
    'export-shell-version')
    printf "%s %s\n" "$asdf_cmd_dir/command-$1.bash" 2
    ;;

  '' | '--help' | '-h' | 'help')
    printf "%s %s\n" "$asdf_cmd_dir/command-help.bash" 2
    ;;

  '--version' | 'version')
    printf "%s %s\n" "$asdf_cmd_dir/command-version.bash" 2
    ;;

  *)
    find_cmd "$asdf_cmd_dir" "$@"
    ;;
  esac
}

find_plugin_cmd() {
  local ASDF_CMD_FILE args_offset
  local result=
  result="$(find_cmd "$(get_plugin_path "$1")/lib/commands" "${@:2}")"
  ASDF_CMD_FILE=${result% *}
  args_offset=${result##* }
  if [ -n "$ASDF_CMD_FILE" ]; then
    args_offset=$((args_offset + 1)) # since the first argument is the plugin name
    printf "%s %s\n" "$ASDF_CMD_FILE" "$args_offset"
  fi
}

asdf_cmd() {
  local ASDF_CMD_FILE args_offset

  if [ "shell" = "$1" ]; then
    printf "Shell integration is not enabled. Please ensure you source asdf in your shell setup." >&2
    exit 1
  fi

  # Internal Variables
  ASDF_DEFAULT_TOOL_VERSIONS_FILENAME=$(asdf_tool_versions_filename)
  export ASDF_DEFAULT_TOOL_VERSIONS_FILENAME

  ASDF_CONFIG_FILE=$(asdf_config_file)
  export ASDF_CONFIG_FILE

  ASDF_DATA_DIR=$(asdf_data_dir)
  export ASDF_DATA_DIR

  ASDF_DIR=$(asdf_dir)
  export ASDF_DIR

  local result=
  result="$(find_asdf_cmd "$@")"
  ASDF_CMD_FILE=${result% *}
  args_offset=${result##* }
  if [ -z "$ASDF_CMD_FILE" ]; then
    result="$(find_plugin_cmd "$@")"
    ASDF_CMD_FILE=${result% *}
    args_offset=${result##* }
  fi

  if [ -x "$ASDF_CMD_FILE" ]; then
    # When '$ASDF_CMD_FILE' is an executable, we are executing a command directly from a plugin.
    # Example: https://github.com/asdf-community/asdf-nim/blob/397c14a7f04ad5b91963814afc2e9cc92366e1c5/lib/commands/command-install-deps.bash
    # In those cases, the path to that command is always an absolute path. However, this codepath can also be activated if a user accidentally
    # marks files in ./lib/commands/* as executable. This code detects when that happens and prints a useful warning message.
    if [[ "$ASDF_CMD_FILE" == ./lib/commands/* ]]; then
      printf '%s\n' "----------"
      printf '%s\n' "asdf: Warning: You are executing an asdf command from \$ASDF_DIR, but we detected that some files have been"
      printf '%s\n' "               erroneously marked as executable. All files under '$ASDF_DIR/lib/commands' must NOT be marked"
      printf '%s\n' "               as executable. Otherwise, asdf will not be able to source its core files"
      printf '%s\n' "----------"
    fi >&2

    exec "$ASDF_CMD_FILE" "${@:${args_offset}}"
  elif [ -f "$ASDF_CMD_FILE" ]; then
    print_0_16_0_migration_notice
    set -- "${@:${args_offset}}"
    # shellcheck source=/dev/null
    . "$ASDF_CMD_FILE"
  else
    local asdf_cmd_dir
    asdf_cmd_dir="$(asdf_dir)/lib/commands"
    printf "%s\n" "Unknown command: \`asdf ${*}\`" >&2
    # shellcheck source=lib/commands/command-help.bash
    . "$asdf_cmd_dir/command-help.bash" >&2
    return 127
  fi
}

print_0_16_0_migration_notice() {
  printf -- '\033[1;31m----------

NOTICE:

You have tried to upgrade to asdf 0.16.0 or newer. Versions 0.16.0 is a
complete rewrite of asdf in Go. This text is being printed by the older
Bash implementation. If you are seeing this you have not migrated to
asdf 0.16.0. Please follow the instructions on the upgrade guide to
migrate to the new version.

Aside from this notice, this older Bash implementation works as it did
in asdf version 0.15.0 and older.

Migration guide: https://asdf-vm.com/guide/upgrading-to-v0-16
asdf website: https://asdf-vm.com
Source code: https://github.com/asdf-vm/asdf
\033[0m\n\n' >&2
}

asdf_cmd "$@"
