#!/usr/bin/env bash

rdo_header machine

rdo_machine() {
  local cmd="${1}"; shift || :

  case "${cmd}" in
    create)
      rdo_machine_create "${@}"
      ;;
    current)
      rdo_machine_current_name "${@}"
      ;;
    destroy)
      rdo_machine_destroy "${@}"
      ;;
    start)
      rdo_machine_start "${@}"
      ;;
    status)
      rdo_machine_status "${@}"
      ;;
    stop)
      rdo_machine_stop "${@}"
      ;;
    --help|-h|'')
      echo "Usage: rdo machine COMMAND"
      echo
      echo "Create and manage rtorrent-docker machines"
      echo
      echo "Commands"
      echo "  create   Initalize the docker machine"
      echo "  current  Print the current docker machine name"
      echo "  destroy  Destroy the docker machine"
      echo "  start    Start the docker machine"
      echo "  status   Print the status of the docker machine"
      echo "  stop     Stop the docker machine"
      echo
      echo "Run 'rdo machine COMMAND --help' for more information on a command."
      ;;
    *)
      print_error "rdo machine: unknown command: ${@}"
      return 1
      ;;
  esac
}

rdo_machine_create() {
  local arg_cpu_count="$(rdo__machine_cpu_count)"
  local arg_disk_size=100000
  local arg_docker_machine=
  local arg_memory="$(rdo__machine_memory)"

  local create_args=()

  while [[ -n "${1}" ]]; do
    case "${1}" in
      --docker-machine)
        arg_docker_machine="${2:?Missing docker machine name.}"
        shift 2 ;;
      --help|-h)
        echo "Usage: rdo machine create [OPTIONS]"
        echo
        echo "Create and manage rtorrent-docker environment"
        echo
        echo "Options:"
        echo "      --docker-machine NAME  Set docker machine name"
        echo
        echo "Run 'rdo machine create --help' for more information on a command."
        exit 1
        ;;
      *)
        rdo__args__check_empty rdo_machine_create "${@}" && break || exit 1
        ;;
    esac
  done

  rdo__args__check_valid_arg arg_cpu_count || exit 1
  rdo__args__check_valid_arg arg_docker_machine || exit 1
  rdo__args__check_valid_arg arg_memory || exit 1

  if [[ "${OSTYPE}" == "cygwin" ]]; then
    # create_args+=("--virtualbox-share-folder" "$(rdo__project_absolute_path)")
     create_args+=("--virtualbox-share-folder" 'c:\cygwin64:cygwin64')
    :
  fi

  create_args+=("--virtualbox-cpu-count" "${arg_cpu_count}")
  create_args+=("--virtualbox-disk-size" "${arg_disk_size}")
  create_args+=("--virtualbox-memory" "${arg_memory}")

  print_progress "creating docker machine '${arg_docker_machine}' (cpu:${arg_cpu_count} memory:${arg_memory} disk_size:${arg_disk_size})"

  if [[ -f "${DATA_PATH}/env.machine" ]] && [[ -z "$(rdo_machine__current_name)" ]]; then
    print_error "removing invalid env.machine file"
    rm -f "${DATA_PATH}/env.machine"
  fi

  rdo_machine__attempt_start "${arg_docker_machine}"

  if [[ -z "$(docker-machine inspect "${arg_docker_machine}")" ]]; then
    print_normal "creating docker machine '${arg_docker_machine}'"
    docker-machine create "${create_args[@]}" --driver virtualbox "${arg_docker_machine}"
  else
    print_normal "docker machine '${arg_docker_machine}' already exists, skipping creation"
  fi

  if rdo_machine__is_error "${arg_docker_machine}"; then
    print_error "unable to create docker machine"
    exit 1
  fi

  print_normal "updating env.machine with '${arg_docker_machine}'"
  docker-machine env "${arg_docker_machine}" > "${DATA_PATH}/env.machine"
}

rdo_machine_destroy() {
  local machine_name="$(rdo_machine__current_name)"

  print_progress "destroying docker machine '${machine_name}'"

  if [[ -z "${machine_name}" ]]; then
    print_normal "docker machine not initialized, skipping"
    return
  fi

  if [[ -n "$(docker-machine ls --quiet --filter "name=${machine_name}")" ]]; then
    print_normal "killing docker machine '${machine_name}'"
    docker-machine rm -y "${machine_name}"
  else
    print_normal "docker machine not found, skipping"
  fi

  rm "${DATA_PATH}/env.machine"
}

rdo_machine_start() {
  local machine_name="$(rdo_machine__current_name)"

  if [[ -z "${machine_name}" ]]; then
    print_error "could not start docker machine, machine not defined"
    return 1
  fi

  print_progress "starting docker machine '${machine_name}'"
  docker-machine start "${machine_name}"
}

rdo_machine_status() {
  local machine_name="${1:-$(rdo_machine__current_name)}"
  docker-machine status "${machine_name}"
}

rdo_machine_stop() {
  local machine_name="$(rdo_machine__current_name)"

  if [[ -z "${machine_name}" ]]; then
    print_warning "could not stop docker machine, machine not defined"
    return 1
  fi

  print_progress "stopping docker machine '${machine_name}'"
  docker-machine stop "${machine_name}"
}

# Helper functions

rdo_machine__has_env() {
  [[ -f "${DATA_PATH}/env.machine" ]] && grep 'DOCKER_MACHINE_NAME=' "${DATA_PATH}/env.machine" &> /dev/null
}

rdo_machine__current() {
  local machine_name="$(rdo_machine__current_name)"
  [[ -z "${machine_name}" ]] && (print_progress "docker machine not initialized"; return 1)
  echo "${machine_name}"
}

rdo_machine__current_name() {
  [[ -f "${DATA_PATH}/env.machine" ]] || return
  sed -e '/DOCKER_MACHINE_NAME/!d; s/"//g; s/export DOCKER_MACHINE_NAME=//' "${DATA_PATH}/env.machine"
}

rdo_machine__status() {
  local machine_name="${1:?Missing machine name argument.}"
  docker-machine status "${machine_name}" 2> /dev/null
}

rdo_machine__is_active() {
  local machine_name="${1:?Missing machine name argument.}"
  [[ "${machine_name}" == "$(docker-machine active)" ]]
}

rdo_machine__is_created() {
  [[ -n "$(rdo_machine__status "${@}")" ]]
}

rdo_machine__is_error() {
  local machine_name="${1:?Missing machine name argument.}"
  [[ "$(docker-machine ls --format '{{ .State }}' --filter "name=${machine_name}")" == "Error" ]]
}

rdo_machine__is_running() {
  [[ "$(rdo_machine__status "${@}")" == "Running" ]]
}

rdo_machine__is_saved() {
  [[ "$(rdo_machine__status "${@}")" == "Saved" ]]
}

rdo_machine__is_stopped() {
  [[ "$(rdo_machine__status "${@}")" == "Stopped" ]]
}

rdo_machine__attempt_start() {
  local machine_name="${1:?Missing machine name argument.}"

  if rdo_machine__is_saved "${machine_name}"; then
    print_normal "starting saved docker machine"
    docker-machine start "${machine_name}"
  fi

  if rdo_machine__is_stopped "${machine_name}"; then
    print_normal "docker machine '${machine_name}' is stopped, restarting"
    docker-machine start "${machine_name}"
  fi

  if rdo_machine__is_error "${machine_name}"; then
    print_normal "removing invalid docker machine"
    docker-machine rm -f "${machine_name}"
  fi
}

rdo_machine__verify() {
  local machine_name="$(rdo_machine__current_name)"

  if ! docker-machine active &> /dev/null; then
    print_error "docker machine command active failed"
    exit 1
  fi

  local active_machine="$(docker-machine active)"

  if [[ "${active_machine}" != "${machine_name}" ]]; then
    print_error "docker machine mismatch, expected '${machine_name}' got '${active_machine}'"
    print_error "use './do bash' to enter custom bash session"
    exit 1
  fi
}
