#!/bin/bash
set -euo pipefail
IFS=$'\n\t'

# shellcheck source=start-utils
. "$(dirname "$0")/start-utils"

: "${EULA:=}"
: "${PROXY:=}"
: "${ENABLE_AUTOPAUSE:=false}"
: "${ENABLE_AUTOSTOP:=false}"
: "${RCON_CMDS_STARTUP:=}"
: "${RCON_CMDS_ON_CONNECT:=}"
: "${RCON_CMDS_ON_DISCONNECT:=}"
: "${RCON_CMDS_FIRST_CONNECT:=}"
: "${RCON_CMDS_LAST_DISCONNECT:=}"
: "${RCON_CMDS_PERIOD:=10}"
: "${ENABLE_RCON:=true}"
: "${RCON_PORT:=25575}"
export ENABLE_RCON RCON_PORT

: "${MEMORY=1G}"
: "${INIT_MEMORY=${MEMORY}}"
: "${MAX_MEMORY=${MEMORY}}"
export MEMORY INIT_MEMORY MAX_MEMORY

shopt -s nullglob

isDebugging && set -x

if (( $(mc-image-helper java-release) >= 17 )); then
  MC_IMAGE_HELPER_OPTS+=" --enable-native-access=ALL-UNNAMED"
  export MC_IMAGE_HELPER_OPTS
fi

export HOME=/data

log "Running as uid=$(id -u) gid=$(id -g) with /data as '$(ls -lnd /data)'"
log "Image info: $(paste -d, -s /etc/image.properties)"

if [ ! -e /data/eula.txt ]; then
  if ! isTrue "$EULA"; then
    log ""
    logError "Please accept the Minecraft EULA at"
    logError "  https://account.mojang.com/documents/minecraft_eula"
    logError "by adding the following immediately after 'docker run':"
    logError "  -e EULA=TRUE"
    log ""
    exit 1
  fi

  writeEula
fi

if isTrue "${DEBUG_MEMORY:-false}"; then
  log "Memory usage and availability (in MB)"
  uname -pars | applyLogPrefix
  free -m | applyLogPrefix
fi

##########################################
# Setup RCON password

if isTrue "${ENABLE_RCON:-true}"; then
  # turn off debug output
  set +x

  if [[ -v RCON_PASSWORD_FILE ]]; then
    if [ ! -e "${RCON_PASSWORD_FILE}" ]; then
      log ""
      logError "Initial RCON password file ${RCON_PASSWORD_FILE} does not seems to exist."
      logError "Please ensure your configuration."
      logError "If you are using Docker Secrets feature, please check this for further information: "
      logError " https://docs.docker.com/engine/swarm/secrets"
      log ""
      exit 1
    else
      RCON_PASSWORD=$(cat "${RCON_PASSWORD_FILE}")
      export RCON_PASSWORD
    fi
  elif ! [[ -v RCON_PASSWORD ]]; then
    RCON_PASSWORD=$(openssl rand -hex 12)
    export RCON_PASSWORD
  fi

  # For rcon-cli access running via exec, which by default is running as root
  echo "password=${RCON_PASSWORD}" > "$HOME/.rcon-cli.env"
  echo "password: \"${RCON_PASSWORD}\"" > "$HOME/.rcon-cli.yaml"

  isDebugging && set -x
else
  rm -f "$HOME/.rcon-cli.env" "$HOME/.rcon-cli.yaml"
fi

##########################################
# Auto-pause/stop

if isTrue "${ENABLE_AUTOPAUSE}" && isTrue "${ENABLE_AUTOSTOP}"; then
    logError "ENABLE_AUTOPAUSE=true is incompatible with ENABLE_AUTOSTOP=true"
    exit 1
fi

proxyArgs=()
if [[ $PROXY ]]; then
    export http_proxy="$PROXY"
    export https_proxy="$PROXY"

    IFS=":"
    read -ra parts <<< "$PROXY"
    IFS=" "
    : "${PROXY_HOST=$(firstArrayElement parts)}"
    shiftArray parts
    : "${PROXY_PORT=$(firstArrayElement parts)}"
fi

# https://docs.oracle.com/javase/7/docs/api/java/net/doc-files/net-properties.html
proxyArgs=()
function addToProxyArgs() {
  if [[ $2 ]]; then
    proxyArgs+=("-D$1=$2")
  fi
}
addToProxyArgs http.proxyHost "${PROXY_HOST:-}"
addToProxyArgs http.proxyPort "${PROXY_PORT:-}"
addToProxyArgs http.nonProxyHosts "${PROXY_NON_PROXY_HOSTS:-}"
LOCAL_IFS=$IFS; IFS=' '; MC_IMAGE_HELPER_OPTS+=" ${proxyArgs[*]}"; IFS=$LOCAL_IFS
export MC_IMAGE_HELPER_OPTS

function fixJavaPath() {
  # Some Docker management UIs grab all the image declared variables and present them for configuration.
  # When upgrading images across Java versions, that creates parts mismatch in PATH's expected by base image.
  if ! which java > /dev/null; then
    logError "       Your Docker provider has an annoying flaw where it"
    logError "       tries to set PATH even though the container establishes"
    logError "       parts very specific value."
    sleep 2
    # now find where java might be
    for d in /opt/java/openjdk/bin /usr/bin; do
      if [ -x "${d}/java" ]; then
        PATH="${PATH}:${d}"
        return 0
      fi
    done
    return 1
  fi
}


if ! fixJavaPath; then
  logError "could not locate path that contains java"
  exit 1
fi

cd /data || exit 1

##########################################
# Optionally load environment variables from a file or archive entry,
# allowing packs/artifacts to declare TYPE, VERSION and other settings
# inside-out. Loaded values override anything passed in through docker -e.
# Generic packs are processed first so that LOAD_ENV_FROM_FILE and
# LOAD_ENV_FROM_ARCHIVE can override any values they set.

if isTrue "${LOAD_ENV_FROM_GENERIC_PACK:-false}"; then
  if ! loadEnvFromGenericPack; then
    exit 1
  fi
fi

if [[ ${LOAD_ENV_FROM_FILE:-} ]]; then
  if ! loadEnvFromFile "${LOAD_ENV_FROM_FILE}"; then
    exit 1
  fi
fi

if [[ ${LOAD_ENV_FROM_ARCHIVE:-} ]]; then
  if ! loadEnvFromArchive "${LOAD_ENV_FROM_ARCHIVE}" "${LOAD_ENV_FROM_ARCHIVE_ENTRY:-.env}"; then
    exit 1
  fi
fi

export DECLARED_TYPE=${TYPE^^}
export DECLARED_VERSION="$VERSION"

if isTrue "${VERSION_FROM_MODRINTH_PROJECTS:-}" && [[ ${MODRINTH_PROJECTS:-} ]]; then
  args=()
  if [[ ${MODRINTH_PROJECTS_DEFAULT_VERSION_TYPE:-} ]]; then
    args+=(--allowed-version-type "${MODRINTH_PROJECTS_DEFAULT_VERSION_TYPE:-}")
  fi
  if ! VERSION=$(mc-image-helper version-from-modrinth-projects "${args[@]}" --projects "${MODRINTH_PROJECTS}"); then
    logError "failed to resolve version from MODRINTH_PROJECTS: ${MODRINTH_PROJECTS}"
    exit 1
  fi
  log "Resolved Minecraft version $VERSION from Modrinth projects"
  export VERSION
fi

if isTrue "${ENABLE_AUTOPAUSE}"; then
  "$(dirname "$0")/start-autopause"
elif isTrue "${ENABLE_AUTOSTOP}"; then
  "$(dirname "$0")/start-autostop"
fi

if
  [[ "$RCON_CMDS_STARTUP" ]] ||
  [[ "$RCON_CMDS_ON_CONNECT" ]] ||
  [[ "$RCON_CMDS_ON_DISCONNECT" ]] ||
  [[ "$RCON_CMDS_FIRST_CONNECT" ]] ||
  [[ "$RCON_CMDS_LAST_DISCONNECT" ]]
then
  log "Starting RCON commands"
  # shellcheck source=start-rconcmds
  "$(dirname "$0")/start-rconcmds"
fi

: "${MODPACK_PLATFORM:=${MOD_PLATFORM:-}}"

if [[ $MODPACK_PLATFORM && $TYPE && $TYPE != VANILLA ]]; then
  logWarning "Avoid setting TYPE and MODPACK_PLATFORM"
fi

case "${TYPE^^}" in
  AUTO_CURSEFORGE|MODRINTH|CURSEFORGE|FTB|FTBA|GTNH)
    MODPACK_PLATFORM="$TYPE"
  ;;
esac

if [[ $MODPACK_PLATFORM ]]; then
  case "${MODPACK_PLATFORM^^}" in
    FTB|CURSEFORGE)
      exec "$(dirname "$0")/start-deployCF" "$@"
    ;;

    FTBA)
      exec "$(dirname "$0")/start-deployFTBA" "$@"
    ;;

    AUTO_CURSEFORGE)
      exec "$(dirname "$0")/start-deployAutoCF" "$@"
      ;;

    MODRINTH)
      exec "$(dirname "$0")/start-deployModrinth" "$@"
      ;;

    GTNH)
      exec "$(dirname "$0")/start-deployGTNH" "$@"
      ;;

    *)
      logError "Invalid MODPACK_PLATFORM: '$MODPACK_PLATFORM'"
      exit 1
      ;;
  esac
fi

log "Resolving type given ${TYPE}"
case "${TYPE^^}" in
  *BUKKIT|SPIGOT)
    exec "$(dirname "$0")/start-deployBukkitSpigot" "$@"
  ;;

  PAPER)
    exec "$(dirname "$0")/start-deployPaper" "$@"
  ;;

  FOLIA)
    exec "$(dirname "$0")/start-deployFolia" "$@"
  ;;

  FORGE)
    exec "$(dirname "$0")/start-deployForge" "$@"
  ;;

  NEOFORGE|NEOFORGED)
    exec "$(dirname "$0")/start-deployNeoForge" "$@"
  ;;

  FABRIC)
    exec "$(dirname "$0")/start-deployFabric" "$@"
  ;;

  QUILT)
    exec "$(dirname "$0")/start-deployQuilt" "$@"
  ;;

  VANILLA)
    exec "$(dirname "$0")/start-deployVanilla" "$@"
  ;;

  SPONGEVANILLA)
    exec "$(dirname "$0")/start-deploySpongeVanilla" "$@"
  ;;

  CUSTOM)
    exec "$(dirname "$0")/start-deployCustom" "$@"
  ;;

  MAGMA)
    exec "$(dirname "$0")/start-deployMagma" "$@"
  ;;

  MAGMA_MAINTAINED)
    exec "$(dirname "$0")/start-deployMagmaMaintained" "$@"
  ;;

  KETTING)
    exec "$(dirname "$0")/start-deployKetting" "$@"
  ;;

  MOHIST|YOUER|BANNER)
    exec "$(dirname "$0")/start-deployMohist" "$@"
  ;;

  PURPUR)
    exec "$(dirname "$0")/start-deployPurpur" "$@"
  ;;

  PUFFERFISH)
    exec "$(dirname "$0")/start-deployPufferfish" "$@"
  ;;

  CANYON)
    exec "$(dirname "$0")/start-deployCanyon" "$@"
  ;;

  LIMBO)
    exec "$(dirname "$0")/start-deployLimbo" "$@"
  ;;

  NANOLIMBO)
    exec "$(dirname "$0")/start-deployNanoLimbo" "$@"
  ;;

  CRUCIBLE)
    exec "$(dirname "$0")/start-deployCrucible" "$@"
  ;;

  LEAF)
    exec "$(dirname "$0")/start-deployLeaf" "$@"
  ;;

  ARCLIGHT)
    exec "$(dirname "$0")/start-deployArcLight" "$@"
  ;;

  POSEIDON)
    exec "$(dirname "$0")/start-deployPoseidon" "$@"
  ;;

  *)
      logError "Invalid TYPE: '$TYPE'"
      logError "Must be: VANILLA, FORGE, BUKKIT, SPIGOT, PAPER, FOLIA, PURPUR, FABRIC, QUILT,"
      logError "         SPONGEVANILLA, CUSTOM, MAGMA, MOHIST, GTNH, AIRPLANE, PUFFERFISH,"
      logError "         CANYON, LIMBO, NANOLIMBO, CRUCIBLE, LEAF, YOUER, BANNER, NEOFORGE"
      exit 1
  ;;

esac
