#!/usr/bin/env bash

set -e -o pipefail

CDPATH=""

SCRIPT="$0"

UNAME=$(uname -s)
if [ $UNAME = "FreeBSD" ]; then
  OS="freebsd"
elif [ $UNAME = "Darwin" ]; then
  OS="darwin"
else
  OS="other"
fi

# SCRIPT might be an arbitrarily deep series of symbolic links; loop until we
# have the concrete path
while [ -h "$SCRIPT" ] ; do
  ls=`ls -ld "$SCRIPT"`
  # Drop everything prior to ->
  link=`expr "$ls" : '.*-> \(.*\)$'`
  if expr "$link" : '/.*' > /dev/null; then
    SCRIPT="$link"
  else
    SCRIPT=`dirname "$SCRIPT"`/"$link"
  fi
done

if [[ -z "$LUCENIA_HOME" ]]; then
  # determine OpenSearch home; to do this, we strip from the path until we find
  # bin, and then strip bin (there is an assumption here that there is no nested
  # directory under bin also named bin)
  LUCENIA_HOME=`dirname "$SCRIPT"`

  # now make LUCENIA_HOME absolute
  LUCENIA_HOME=`cd "$LUCENIA_HOME"; pwd`

  while [ "`basename "$LUCENIA_HOME"`" != "bin" ]; do
    LUCENIA_HOME=`dirname "$LUCENIA_HOME"`
  done
  LUCENIA_HOME=`dirname "$LUCENIA_HOME"`
fi

# now set the classpath
LUCENIA_CLASSPATH="$LUCENIA_HOME/lib/*"

# now set the path to java: LUCENIA_JAVA_HOME -> JAVA_HOME -> bundled JRE -> bundled JDK
if [ ! -z "$LUCENIA_JAVA_HOME" ]; then
  JAVA="$LUCENIA_JAVA_HOME/bin/java"
  JAVA_TYPE="LUCENIA_JAVA_HOME"
elif [ ! -z "$JAVA_HOME" ]; then
  JAVA="$JAVA_HOME/bin/java"
  JAVA_TYPE="JAVA_HOME"
else
  if [ $OS = "darwin" ]; then
    # Attempt to use bundled Java first
    # However, some systems may opt to use the arm64 tar.gz instead
    # of a darwin build. For this reason, the bundled jdk may not work.
    # Bundled darwin java is not provided on the arm64 tar.gz version
    JAVA="$LUCENIA_HOME/jdk.app/Contents/Home/bin/java"
    JAVA_TYPE="bundled jdk"

    if [ ! -x "$JAVA" ]; then
      echo "⚠️  Bundled JDK not found at $JAVA. Falling back to system Java."

      # Try system java instead
      JAVA=$(which java 2>/dev/null)
      if [ -z "$JAVA" ]; then
        echo "❌ No system Java found. Please install Java 21+ (e.g., via Homebrew: brew install openjdk@21)"
        exit 1
      fi

      # Check Java version (expecting version string like "21.0.x")
      JAVA_VERSION=$("$JAVA" -version 2>&1 | awk -F[\".] '/version/ {print $2}')
      if [ -z "$JAVA_VERSION" ] || [ "$JAVA_VERSION" -lt 21 ]; then
        echo "❌ System Java version is too old. Found version $JAVA_VERSION. Please install Java 21+."
        exit 1
      fi

      JAVA_TYPE="system java"
    fi
    echo "✅ Using $JAVA_TYPE at $JAVA"

  elif [ $OS = "freebsd" ]; then
    # using FreeBSD default java from ports if JAVA_HOME is not set
    JAVA="/usr/local/bin/java"
    JAVA_TYPE="bundled jdk"
  elif [ -d "$LUCENIA_HOME/jre" ]; then
    JAVA="$LUCENIA_HOME/jre/bin/java"
    JAVA_TYPE="bundled jre"
  else
    JAVA="$LUCENIA_HOME/jdk/bin/java"
    JAVA_TYPE="bundled jdk"
  fi
fi

if [ ! -x "$JAVA" ]; then
    echo "could not find java in $JAVA_TYPE at $JAVA" >&2
    exit 1
  fi

# do not let JAVA_TOOL_OPTIONS slip in (as the JVM does by default)
if [ ! -z "$JAVA_TOOL_OPTIONS" ]; then
  echo "warning: ignoring JAVA_TOOL_OPTIONS=$JAVA_TOOL_OPTIONS"
  unset JAVA_TOOL_OPTIONS
fi

# JAVA_OPTS is not a built-in JVM mechanism but some people think it is so we
# warn them that we are not observing the value of $JAVA_OPTS
if [ ! -z "$JAVA_OPTS" ]; then
  echo -n "warning: ignoring JAVA_OPTS=$JAVA_OPTS; "
  echo "pass JVM parameters via LUCENIA_JAVA_OPTS"
fi

if [[ "$("$JAVA" -version 2>/dev/null)" =~ "Unable to map CDS archive" ]]; then
  XSHARE="-Xshare:off"
else
  XSHARE="-Xshare:auto"
fi

# check the Java version
"$JAVA" "$XSHARE" -cp "$LUCENIA_CLASSPATH" io.lucenia.tools.java_version_checker.JavaVersionChecker

export HOSTNAME=$HOSTNAME

if [ -z "$LUCENIA_PATH_CONF" ]; then
  if [ -z "$LUCENIA_PATH_CONF" ]; then LUCENIA_PATH_CONF="$LUCENIA_HOME"/config; fi
fi

if [ -z "$LUCENIA_PATH_CONF" ]; then
  echo "LUCENIA_PATH_CONF must be set to the configuration path"
  exit 1
fi

# now make LUCENIA_PATH_CONF absolute
LUCENIA_PATH_CONF=`cd "$LUCENIA_PATH_CONF"; pwd`

LUCENIA_DISTRIBUTION_TYPE=zip
LUCENIA_BUNDLED_JDK=true

if [[ "$LUCENIA_BUNDLED_JDK" == "false" ]]; then
  echo "warning: no-jdk distributions that do not bundle a JDK are deprecated and will be removed in a future release" >&2
fi

if [[ "$LUCENIA_DISTRIBUTION_TYPE" == "docker" ]]; then
  # Allow environment variables to be set by creating a file with the
  # contents, and setting an environment variable with the suffix _FILE to
  # point to it. This can be used to provide secrets to a container, without
  # the values being specified explicitly when running the container.
  source "$LUCENIA_HOME/bin/lucenia-env-from-file"

  # Parse Docker env vars to customize OpenSearch
  #
  # e.g. Setting the env var cluster.name=testcluster
  #
  # will cause OpenSearch to be invoked with -Ecluster.name=testcluster
  #
  # see https://opensearch.org/docs/opensearch/configuration/

  declare -a lucenia_arg_array

  while IFS='=' read -r envvar_key envvar_value
  do
    # Lucenia settings need to have at least two dot separated lowercase
    # words, e.g. `cluster.name`
    if [[ "$envvar_key" =~ ^[a-z0-9_]+\.[a-z0-9_]+ ]]; then
      if [[ ! -z $envvar_value ]]; then
        lucenia_opt="-E${envvar_key}=${envvar_value}"
        lucenia_arg_array+=("${lucenia_opt}")
      fi
    fi
  done < <(env)

  # Reset the positional parameters to the lucenia_arg_array values and any existing positional params
  set -- "$@" "${lucenia_arg_array[@]}"

  # The virtual file /proc/self/cgroup should list the current cgroup
  # membership. For each hierarchy, you can follow the cgroup path from
  # this file to the cgroup filesystem (usually /sys/fs/cgroup/) and
  # introspect the statistics for the cgroup for the given
  # hierarchy. Alas, Docker breaks this by mounting the container
  # statistics at the root while leaving the cgroup paths as the actual
  # paths. Therefore, Lucenia provides a mechanism to override
  # reading the cgroup path from /proc/self/cgroup and instead uses the
  # cgroup path defined the JVM system property
  # lucenia.cgroups.hierarchy.override. Therefore, we set this value here so
  # that cgroup statistics are available for the container this process
  # will run in.
  export LUCENIA_JAVA_OPTS="-Dlucenia.cgroups.hierarchy.override=/ $LUCENIA_JAVA_OPTS"
fi

cd "$LUCENIA_HOME"
