#!/bin/bash
set -o pipefail

script_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
msh_home=`realpath $script_dir/..`

source "$msh_home/lib/defaults.cf"
[ -f "$msh_home/etc/config.cf" ] && source "$msh_home/etc/config.cf"
source "$msh_home/lib/functions.sh"

mkdir -p "$msh_home/var/log"
# Snapshots are staged here instead of /tmp, which is often a small tmpfs.
mkdir -p "$msh_home/var/tmp"

# Older nodes kept their attachment files in var/node/attachments; the node and the milter now
# use var/attachments. Move them over once, keeping any file already there.
old_attachments_dir="$msh_home/var/node/attachments"
if [ -d "$old_attachments_dir" ]; then
  mkdir -p "$msh_home/var/attachments"
  cp -an "$old_attachments_dir"/. "$msh_home/var/attachments/" \
    && rm -rf "$old_attachments_dir" \
    && rmdir "$msh_home/var/node" 2>/dev/null
fi

# Log file for this launcher. Lines emitted via log_info/log_error also go to the
# systemd journal, so they show up in `systemctl status` / `journalctl`.
MSH_LOG_FILE="$msh_home/var/log/node.out"
: > "$MSH_LOG_FILE"

# The node keeps its copy of the master, which the milter reads, and reads the milter's events.
node_db_path="$(db_file_path "$NODE_DB_FILENAME")"
milter_db_path="$(db_file_path "$MILTER_DB_FILENAME")"

# 1) Verify Java executable
if [ -z "$MSH_JAVA_BIN" ]; then
  log_error "MSH_JAVA_BIN is not set!"
  sleep 1
  exit 1
fi

java_bin=""
if [ -x "$MSH_JAVA_BIN" ]; then
  java_bin="$MSH_JAVA_BIN"
else
  java_bin="$(command -v "$MSH_JAVA_BIN" 2>/dev/null || true)"
fi

if [ -z "$java_bin" ] || [ ! -x "$java_bin" ]; then
  log_error "MSH_JAVA_BIN ('$MSH_JAVA_BIN') does not point to a valid executable."
  sleep 1
  exit 1
fi

# 2) Check Java version is at least 21
ver_output="$("${java_bin}" -version 2>&1 || true)"
version_str="$(printf '%s\n' "$ver_output" | head -n1 | sed -E 's/.*version "([^"]+)".*/\1/')"

if [[ -z "${version_str}" ]]; then
  log_error "Unable to determine Java version from: ${ver_output}"
  sleep 1
  exit 1
fi

if [[ "${version_str}" == 1.* ]]; then
  major_ver="$(printf '%s' "${version_str}" | cut -d. -f2)"
else
  major_ver="$(printf '%s' "${version_str}" | cut -d. -f1)"
fi

# Ensure major_ver is numeric
if ! [[ "${major_ver}" =~ ^[0-9]+$ ]]; then
  log_error "Unrecognized Java version: ${version_str}"
  sleep 1
  exit 1
fi

if (( major_ver < 21 )); then
  log_error "Java ${version_str} detected. Java 21+ is required."
  sleep 1
  exit 1
fi

if ! "$java_bin" -version >/dev/null 2>&1; then
  log_error "Failed to execute '$java_bin -version'. Please check your Java installation."
  sleep 1
  exit 1
fi

# The status reports a checksum of the scripts directory (relative to the install dir).
case "$SCRIPTS_DIR" in
  "") scripts_dir="" ;;
  /*) scripts_dir="$SCRIPTS_DIR" ;;
  *)  scripts_dir="$msh_home/$SCRIPTS_DIR" ;;
esac

# Run the node. It creates etc/node.token and its HTTPS certificate (etc/node.p12) on the first
# start; msh-zr-web needs the token and pins the certificate when the server is added. Combined
# output goes to the systemd journal and is appended to the log file via tee.
"$java_bin" \
-Xms$NODE_JAVA_XMS \
-Xmx$NODE_JAVA_XMX \
-Dfile.encoding=UTF8 \
-Djava.io.tmpdir="$msh_home/var/tmp" \
-jar "$msh_home/bin/jar/msh-zr-node.jar" \
--server.port=$NODE_PORT \
--msh.zr.install.dir="$msh_home" \
--msh.zr.node.db.path="$node_db_path" \
--msh.zr.milter.db.path="$milter_db_path" \
--msh.zr.node.milter.port=$MILTER_PORT \
--msh.zr.scripts.dir="$scripts_dir" \
$@ \
2>&1 | tee -a "$MSH_LOG_FILE"
