#!/usr/bin/env bash
set -e
trap 'error "$(printf "Command \`%s\` at $BASH_SOURCE:$LINENO failed with exit code $?" "$BASH_COMMAND")"' ERR

## find directory where this script is located following symlinks if neccessary
readonly WARDEN_DIR="$(
  cd "$(
    dirname "$(
      (readlink "${BASH_SOURCE[0]}" || echo "${BASH_SOURCE[0]}") \
        | sed -e "s#^../#$(dirname "$(dirname "${BASH_SOURCE[0]}")")/#"
    )"
  )/.." >/dev/null \
  && pwd
)"
source "${WARDEN_DIR}/utils/core.sh"
source "${WARDEN_DIR}/utils/env.sh"

## verify docker-compose is installed
if ! which docker-compose >/dev/null; then
  fatal "docker-compose could not be found; please install and try again."
fi

## verify docker-compose meets version constraint
DOCKER_COMPOSE_REQUIRE="1.25.0"
DOCKER_COMPOSE_VERSION="$(docker-compose --version | grep -oE '[0-9\.]+' | head -n1)"
if ! test $(version ${DOCKER_COMPOSE_VERSION}) -ge $(version ${DOCKER_COMPOSE_REQUIRE}); then
  fatal "docker-compose version should be ${DOCKER_COMPOSE_REQUIRE} or higher (${DOCKER_COMPOSE_VERSION} installed)"
fi

## define and export global shared directory paths
export readonly WARDEN_HOME_DIR="${WARDEN_HOME_DIR:-"$HOME/.warden"}"
export readonly WARDEN_SSL_DIR="${WARDEN_HOME_DIR}/ssl"
export readonly WARDEN_COMPOSER_DIR="${WARDEN_COMPOSER_DIR:-"$HOME/.composer"}"

## declare variables for flags and arguments
declare WARDEN_HELP=
declare WARDEN_PARAMS=()
declare WARDEN_CMD_VERB=
declare WARDEN_CMD_EXEC=
declare WARDEN_CMD_HELP=
declare WARDEN_CMD_ANYARGS=(svc env db redis sync shell debug)

## parse first argument as command and determine validity
if (( "$#" )); then
  ## local project directory if running within one; don't fail if it can't be found
  WARDEN_ENV_PATH="$(locateEnvPath 2>/dev/null)" || true

  if [[ -f "${WARDEN_DIR}/commands/${1}.cmd" ]]; then
    WARDEN_CMD_VERB="$1"
    WARDEN_CMD_EXEC="${WARDEN_DIR}/commands/${1}.cmd"
    WARDEN_CMD_HELP="${WARDEN_DIR}/commands/${1}.help"
    shift
  elif [[ -f "${WARDEN_ENV_PATH}/.warden/commands/${1}.cmd" ]]; then
    WARDEN_CMD_VERB="$1"
    WARDEN_CMD_ANYARGS+=("$1")
    WARDEN_CMD_EXEC="${WARDEN_ENV_PATH}/.warden/commands/${1}.cmd"
    WARDEN_CMD_HELP="${WARDEN_ENV_PATH}/.warden/commands/${1}.help"
    shift
  elif [[ -f "${WARDEN_HOME_DIR}/commands/${1}.cmd" ]]; then
    WARDEN_CMD_VERB="$1"
    WARDEN_CMD_ANYARGS+=("$1")
    WARDEN_CMD_EXEC="${WARDEN_HOME_DIR}/commands/${1}.cmd"
    WARDEN_CMD_HELP="${WARDEN_HOME_DIR}/commands/${1}.help"
    shift
  else
    WARDEN_HELP=1
  fi
else
  WARDEN_HELP=1
fi

## parse arguments
while (( "$#" )); do
  case "$1" in
    -h|--help)
      WARDEN_HELP=1
      break
      ;;
    --) # end argument parsing (unless command is on 'anyargs' list and consumes anything as params)
      shift
      containsElement "${WARDEN_CMD_VERB}" "${WARDEN_CMD_ANYARGS[@]}" || break
      ;;
    -*|--*=) # unsupported flags (unless command is on 'anyargs' list and consumes anything as params)
      containsElement "${WARDEN_CMD_VERB}" "${WARDEN_CMD_ANYARGS[@]}" && break
      fatal "Unsupported flag $1"
      ;;
    *) # preserve positional arguments
      WARDEN_PARAMS+=("$1")
      shift
      ;;
  esac
done

## display command specific usage info if help flag is set
if [[ ${WARDEN_HELP} ]]; then
  source "${WARDEN_DIR}/commands/usage.cmd"
fi

## execute sub-command in context of this script
source "${WARDEN_CMD_EXEC}"
