#!/bin/sh

LOG_PREFIX="${LOG_PREFIX:-[app]}"

log() {
  printf '%s %s\n' "${LOG_PREFIX}" "$*"
}

die() {
  printf '%s ERROR: %s\n' "${LOG_PREFIX}" "$*" >&2
  exit 1
}

is_truthy() {
  case "$1" in
    1|[Tt][Rr][Uu][Ee]|[Yy]|[Yy][Ee][Ss]|[Oo][Nn])
      return 0
      ;;
    *)
      return 1
      ;;
  esac
}

require_env() {
  ENV_NAME="$1"
  eval "ENV_VALUE=\${${ENV_NAME}:-}"

  if [ -z "${ENV_VALUE}" ]; then
    die "${ENV_NAME} is required."
  fi
}

assert_safe_data_dir() {
  case "${DATA_DIR:-}" in
    ""|"/")
      die "Refusing to operate on unsafe DATA_DIR='${DATA_DIR:-}'."
      ;;
  esac
}

assert_writable_dir() {
  TARGET_DIR="$1"
  TEST_FILE="${TARGET_DIR}/.writable-check-$$"

  if ! mkdir -p "${TARGET_DIR}" 2>/dev/null; then
    die "Directory '${TARGET_DIR}' cannot be created or accessed by user '$(id -un)' (uid=$(id -u), gid=$(id -g))."
  fi

  if ! : > "${TEST_FILE}" 2>/dev/null; then
    die "Directory '${TARGET_DIR}' is not writable by user '$(id -un)' (uid=$(id -u), gid=$(id -g))."
  fi

  rm -f "${TEST_FILE}"
}

hytale_pid_file_path() {
  printf '%s/server.pid\n' "${RUNTIME_DIR:-/run/hytale}"
}

hytale_fifo_path() {
  printf '%s/stdin.fifo\n' "${RUNTIME_DIR:-/run/hytale}"
}

read_hytale_pid() {
  HYTALE_PID_FILE="$(hytale_pid_file_path)"

  [ -f "${HYTALE_PID_FILE}" ] || return 1

  HYTALE_PID="$(cat "${HYTALE_PID_FILE}" 2>/dev/null || true)"
  case "${HYTALE_PID}" in
    ""|*[!0-9]*)
      return 1
      ;;
  esac

  printf '%s\n' "${HYTALE_PID}"
}

is_hytale_server_running() {
  RUNNING_PID="$(read_hytale_pid)" || return 1
  kill -0 "${RUNNING_PID}" 2>/dev/null
}

assert_hytale_server_stopped() {
  if RUNNING_PID="$(read_hytale_pid)" && kill -0 "${RUNNING_PID}" 2>/dev/null; then
    die "Hytale server is still running with PID ${RUNNING_PID}. Stop the server before running this operation."
  fi
}

gameserver_meta_file() {
  printf '%s\n' "${GAMESERVER_META_FILE:-${DATA_DIR:-/data}/.gameserver-meta.json}"
}

path_relative_to_data_or_absolute() {
  TARGET_PATH="$1"

  case "${TARGET_PATH}" in
    "${DATA_DIR:-/data}"/*)
      printf '%s\n' "${TARGET_PATH#${DATA_DIR}/}"
      ;;
    *)
      printf '%s\n' "${TARGET_PATH}"
      ;;
  esac
}

metadata_value_from_file() {
  META_FILE="$1"
  JQ_FILTER="$2"

  [ -f "${META_FILE}" ] || return 1
  jq -er "${JQ_FILTER} // empty" "${META_FILE}" 2>/dev/null
}

append_jvm_words() {
  JVM_WORDS="$1"

  if [ -z "${JVM_WORDS}" ]; then
    return 0
  fi

  set -f
  for JVM_WORD in ${JVM_WORDS}; do
    printf '%s\n' "${JVM_WORD}"
  done
  set +f
}

write_hytale_jvm_options() {
  JVM_OPTIONS_DIR="$(dirname "${HYTALE_JVM_OPTIONS_FILE}")"
  JVM_OPTIONS_TMP="$(mktemp "${JVM_OPTIONS_DIR}/.jvm.options.XXXXXX")"
  JAVA_XMS_EFFECTIVE="${JAVA_XMS:-${MIN_MEMORY:-}}"
  JAVA_XMX_EFFECTIVE="${JAVA_XMX:-${MAX_MEMORY:-}}"

  {
    printf '%s\n' "# Generated by the Hytale game server image."
    append_jvm_words "${JAVA_OPTS:-}"
    append_jvm_words "${JVM_OPTS:-}"

    if [ -n "${JAVA_XMS_EFFECTIVE}" ]; then
      printf '%s\n' "-Xms${JAVA_XMS_EFFECTIVE}"
    fi

    if [ -n "${JAVA_XMX_EFFECTIVE}" ]; then
      printf '%s\n' "-Xmx${JAVA_XMX_EFFECTIVE}"
    else
      printf '%s\n' "-XX:MaxRAMPercentage=75"
    fi
  } > "${JVM_OPTIONS_TMP}"

  mv "${JVM_OPTIONS_TMP}" "${HYTALE_JVM_OPTIONS_FILE}"
  log "Wrote JVM options to ${HYTALE_JVM_OPTIONS_FILE}."
}

write_gameserver_metadata() {
  META_FILE="$(gameserver_meta_file)"
  META_DIR="$(dirname "${META_FILE}")"
  META_TMP="$(mktemp "${META_DIR}/.gameserver-meta.XXXXXX")"

  LOCAL_HYTALE_VERSION=""
  if [ -f "${META_FILE}" ]; then
    LOCAL_HYTALE_VERSION="$(metadata_value_from_file "${META_FILE}" '.hytaleVersion' || true)"
  fi

  HYTALE_VERSION_EFFECTIVE="${HYTALE_VERSION:-${LOCAL_HYTALE_VERSION:-unknown}}"
  INSTALL_PATH="$(path_relative_to_data_or_absolute "${HYTALE_GAME_DIR:-${DATA_DIR:-/data}/game}")"
  SERVER_JAR_PATH="$(path_relative_to_data_or_absolute "${HYTALE_SERVER_JAR:-${HYTALE_SERVER_DIR:-${HYTALE_GAME_DIR:-${DATA_DIR:-/data}/game}/Server}/HytaleServer.jar}")"
  ASSETS_PATH="$(path_relative_to_data_or_absolute "${HYTALE_ASSETS_ZIP:-${HYTALE_GAME_DIR:-${DATA_DIR:-/data}/game}/Assets.zip}")"

  mkdir -p "${META_DIR}"

  jq -n \
    --arg serverType "${GAMESERVER_SERVER_TYPE:-hytale}" \
    --arg hytaleVersion "${HYTALE_VERSION_EFFECTIVE}" \
    --arg javaVersion "25" \
    --arg installPath "${INSTALL_PATH}" \
    --arg serverJarPath "${SERVER_JAR_PATH}" \
    --arg assetsPath "${ASSETS_PATH}" \
    --arg gamePort "${HYTALE_PORT:-5520}" '
      {
        schemaVersion: 1,
        serverType: $serverType,
        hytaleVersion: $hytaleVersion,
        javaVersion: $javaVersion,
        install: {
          path: $installPath
        },
        artifact: {
          path: $serverJarPath,
          assetsPath: $assetsPath
        },
        network: {
          gamePort: (($gamePort | tonumber?) // $gamePort),
          protocol: "udp"
        }
      }
    ' > "${META_TMP}"

  mv "${META_TMP}" "${META_FILE}"
}
