#!/bin/sh

die() {
  echo "$@" 1>&2
  exit 1
}

realpath () {
(
  TARGET_FILE="$1"

  cd "$(dirname "$TARGET_FILE")"
  TARGET_FILE=$(basename "$TARGET_FILE")

  COUNT=0
  while [ -L "$TARGET_FILE" -a $COUNT -lt 100 ]
  do
      TARGET_FILE=$(readlink "$TARGET_FILE")
      cd "$(dirname "$TARGET_FILE")"
      TARGET_FILE=$(basename "$TARGET_FILE")
      COUNT=$(($COUNT + 1))
  done

  if [ "$TARGET_FILE" = "." -o "$TARGET_FILE" = ".." ]; then
    cd "$TARGET_FILE"
  fi
  TARGET_DIR="$(pwd -P)"
  if [ "$TARGET_DIR" = "/" ]; then
    TARGET_FILE="/$TARGET_FILE"
  else
    TARGET_FILE="$TARGET_DIR/$TARGET_FILE"
  fi
  echo "$TARGET_FILE"
)
}

# ash-template is not designed to be used with Cygwin
is_cygwin() {
  return 1
}

# Allow user and template_declares (see below) to add java options.
addJava () {
  java_opts="$java_opts $1"
}

addApp () {
  app_commands="$app_commands $1"
}

shellEscape () {
  printf "'%s'" "$(printf %s "$1" | sed "s/'/'\\\\''/g")"
}

addResidual () {
  residual_args="$residual_args $(shellEscape "$1")"
}

addDebugger () {
  addJava "-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=$1"
}

require_arg () {
  local type="$1"
  local opt="$2"
  local arg="$3"
  if [ -z "$arg" ] || [ "${arg#-}" != "$arg" ]; then
    die "$opt requires <$type> argument"
  fi
}

# Allow user to specify java options. These get listed first per bash-template.
if [ -n "$JAVA_OPTS" ]
then
  addJava "$JAVA_OPTS"
fi

# Loads a configuration file full of default command line options for this script.
loadConfigFile() {
  cat "$1" | sed '/^\#/d;s/\r$//' | sed 's/^-J-X/-X/' | tr '\r\n' ' '
}

# Detect which JVM we should use.
get_java_cmd() {
  # High-priority override for Jlink images
  if [ -n "$bundled_jvm" ];  then
    echo "$bundled_jvm/bin/java"
  elif [ -n "$JAVA_HOME" ] && [ -x "$JAVA_HOME/bin/java" ];  then
    echo "$JAVA_HOME/bin/java"
  else
    echo "java"
  fi
}

# Processes incoming arguments and places them in appropriate global variables.  called by the run method.
process_args () {
  local no_more_snp_opts=0
  while [ $# -gt 0 ]; do
    case "$1" in
             --) shift && no_more_snp_opts=1 && break ;;
       -h|-help) usage; exit 1 ;;

           -mem) echo "!! WARNING !! -mem option is ignored. Please use -J-Xmx and -J-Xms" && shift 2 ;;
     -jvm-debug) require_arg port "$1" "$2" && addDebugger $2 && shift 2 ;;

          -main) custom_mainclass="$2" && shift 2 ;;

     -java-home) require_arg path "$1" "$2" && jre=`eval echo $2` && java_cmd="$jre/bin/java" && shift 2 ;;

 -D*|-agentlib*|-agentpath*|-javaagent*|-XX*) addJava "$1" && shift ;;
                                         -J*) addJava "$(printf %s "$1"  | sed s/^..//)" && shift ;;
                                           *) addResidual "$1" && shift ;;
    esac
  done

  if [ $no_more_snp_opts -ne 0 ]; then
    while [ $# -gt 0 ]; do
      addResidual "$1" && shift
    done
  fi
}

usage() {
 cat <<EOM
Usage: $script_name [options]

  -h | -help         print this message
  -main <classname>  Define a custom main class
  -jvm-debug <port>  Turn on JVM debugging, open at the given port.

  # java version (default: java from PATH, currently $(java -version 2>&1 | grep version))
  -java-home <path>         alternate JAVA_HOME

  # jvm options and output control
  JAVA_OPTS          environment variable, if unset uses "$java_opts"
  -Dkey=val          pass -Dkey=val directly to the java runtime
  -J-X               pass option -X directly to the java runtime
                     (-J is stripped)

  # special option
  --                 To stop parsing built-in commands from the rest of the command-line.
                     e.g.) enabling debug and sending -d as app argument
                     \$ ./start-script -d -- -d

In the case of duplicated or conflicting options, basically the order above
shows precedence: JAVA_OPTS lowest, command line options highest except "--".
${{available_main_classes}}
EOM
}

app_commands=""
residual_args=""
real_script_path="$(realpath "$0")"
app_home="$(realpath "$(dirname "$real_script_path")")"
lib_dir="$(realpath "${app_home}/../lib")"

app_mainclass=${{app_mainclass}}

${{template_declares}}

process_args "$@"

# Fallback to custom mainclass if main class is not provided (this is the case if the JAR contains multiple apps)
if [ "$app_mainclass" = "" ] || [ $custom_mainclass ];then
  if [ "$custom_mainclass" = "" ]; then
    echo "You need to pass -main argument."
    exit 1
  fi

  app_mainclass=$custom_mainclass
fi

java_cmd="$(get_java_cmd)"

# If a configuration file exist, read the contents to $opts
[ -f "$script_conf_file" ] && opts=$(loadConfigFile "$script_conf_file")

eval "set -- $residual_args"
exec $java_cmd $java_opts -classpath $app_classpath $opts $app_mainclass $app_commands "$@"
