#!/usr/bin/env bash
#
# Docker test environment for rTorrent
#
# https://github.com/rakshasa/rtorrent-docker

set -e

COLOR_NC='\033[0m'
COLOR_RED='\033[0;31m'
COLOR_GREEN='\033[0;32m'

PROJECT_PATH="${BASH_SOURCE[0]%/*}"
PROJECT_ABSOLUTE_PATH=
DATA_PATH="${PROJECT_PATH}/data"

rdo() {
  rdo_included common || source "${PROJECT_PATH}/functions/common"
  rdo_included common.args || source "${PROJECT_PATH}/functions/common.args"
  rdo_included common.container || source "${PROJECT_PATH}/functions/common.container"
  rdo_included common.image || source "${PROJECT_PATH}/functions/common.image"
  rdo_included common.system || source "${PROJECT_PATH}/functions/common.system"

  while true; do
    case "${1}" in
      --debug|-d)
        set -x
        shift ;;
      --help|-h|'help'|'')
        echo "Usage: rdo [OPTIONS] COMMAND"
        echo
        echo "Create and manage rtorrent-docker environment"
        echo
        echo "Options:"
        echo "  -d, --debug   Verbose rsync output"
        echo
        echo "Commands:"
        echo "  bash          Start custom bash session"
        echo "  build         Build projects"
        echo "  destroy       Destroy the environment and optional docker machine"
        echo "  docker        Manage docker containers"
        echo "  init          Initalize the environment and optional docker machine"
        echo "  machine       Manage docker machines"
        echo
        echo "Run 'rdo COMMAND --help' for more information on a command."
        exit 0
        ;;
      *)
        rdo__args__check_unknown_flag rdo "${@}" && break || exit 1 ;;
    esac
  done

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

  case "${cmd}" in
    bash)
      rdo_included machine || source "${PROJECT_PATH}/functions/machine"
      rdo_bash "${@}"
      ;;
    build)
      rdo_included build || source "${PROJECT_PATH}/functions/build"
      rdo_build "${@}"
      ;;
    docker)
      rdo_included docker || source "${PROJECT_PATH}/functions/docker"
      rdo_docker "${@}"
      ;;
    env)
      rdo_included env || source "${PROJECT_PATH}/functions/env"
      rdo_env "${@}"
      ;;
    git)
      rdo_included git || source "${PROJECT_PATH}/functions/git"
      do_git "${@}"
      ;;
    init)
      rdo_included init || source "${PROJECT_PATH}/functions/init"
      rdo_init "${@}"
      ;;
    machine)
      rdo_included machine || source "${PROJECT_PATH}/functions/machine"
      rdo_machine "${@}"
      ;;
    run)
      rdo_included run || source "${PROJECT_PATH}/functions/run"
      rdo_run "${@}"
      ;;
    tags)
      source "${PROJECT_PATH}/functions/tags"
      rdo_tags "${@}"
      ;;

    watch)
      watch -n5 '
        printf "rdo/build/stage:default layers: "
        docker inspect --format "{{ \$length := len .RootFS.Layers }}{{ \$length }}" rdo/build/stage:default
        echo
        docker images |pr -t -2 -o 4 -w 260'
      ;;
    destroy)
      source "${PROJECT_PATH}/functions/machine"
      rdo_machine_destroy
      [[ -f "${DATA_PATH}/"env.* ]] && rm "${DATA_PATH}/"env.*
      ;;
    prune)
      prune_containers
      prune_images
      ;;
    prune-containers)
      prune_containers
      ;;
    prune-images)
      prune_images
      ;;
    clone)
      (
        cd "${DATA_PATH}"
        git clone git@github.com:rakshasa/libtorrent.git
        git clone git@github.com:rakshasa/rtorrent.git
      )
      ;;
    run-build)
      rdo_machine__verify
      main "build"
      "${EXEC_PTY}" docker run --rm -it \
                    --name "rtorrent.current" \
                    rtorrent.build.compile
      ;;
    exec-build)
      "${EXEC_PTY}" docker exec -it dreamy_gauss bash
      ;;
    *)
      print_error "unknown command: ${@}"
      return 1
      ;;
  esac
}

# Print to stderr.
print_normal() {
  echo -e "${@}" >&2
}

print_progress() {
  echo -e "${COLOR_GREEN}${@}${COLOR_NC}" >&2
}

print_error() {
  echo -e "${COLOR_RED}${@}${COLOR_NC}" >&2
}

print_warning() {
  echo -e "${COLOR_RED}${@}${COLOR_NC}" >&2
}

print_space() {
  echo >&2
}

prune_containers() {
  docker container prune --force --filter 'ancestor=rtorrent.ancestor'
}

prune_images() {
  if [[ -n "$(docker images -q --filter 'ancestor=rtorrent.ancestor' --filter 'dangling=true')" ]]; then
    docker rmi --force $(docker images -q --filter 'since=rtorrent.ancestor' --filter 'dangling=true')
  else
    print_progress "no dangling images"
  fi
}

get_project_path() {
  if [[ -z "${PROJECT_PATH}" ]]; then
    print_error "cd_project_path: PROJECT_PATH variable not set"
    exit 1
  fi

  local project_path="$(cd "${PROJECT_PATH}" &> /dev/null && pwd -P)"

  if [[ "${project_path}" == "/" ]]; then
    print_error "cd_project_path: path is root"
    exit 1
  fi

  if [[ -z "${project_path}" ]]; then
    print_error "cd_project_path: failed to enter directory '${PROJECT_PATH}'"
    exit 1
  fi

  echo "${project_path}"
}

rdo_bash() {
  cd "${PROJECT_PATH}"

  if ! [[ -f "${DATA_PATH}/env.bash" ]]; then
    print_error "rdo bash: environment not initialized, could not find '${DATA_PATH}/env.bash'"
    exit 1
  fi

  print_progress "entering custom bash session"
  /usr/bin/env bash --init-file "${DATA_PATH}/env.bash"
  print_warning "exiting custom bash session"
}

declare -A INCLUDED_HEADERS

rdo_header() {
  local header_name="${1:?Missing header name argument.}"

  if [[ -n "${INCLUDED_HEADERS[${header_name}]}" ]]; then
    echo "rdo_${header_name} already included"
    exit 1
  fi

  INCLUDED_HEADERS[${header_name}]="yes"
}

rdo_included() {
  local header_name="${1:?Missing header name argument.}"
  [[ -n "${INCLUDED_HEADERS[${header_name}]}" ]]
}

rdo "${@}"
