#!/usr/bin/env bash

declare -a ARGS=("${@}")

ISMACOS=0
if [ "$( uname -s )" = "Darwin" ]; then
  ISMACOS=1
fi

USAGE="Please use either --installation or --userspace"

DEBUG=0
USERSPACE=0
INSTALLATION=0
DISABLEROOTCHECK=0
for RAWARG in "${@}"; do
  ARG="${RAWARG%%=*}"
  case "${ARG}" in
    --debug)
      DEBUG=1
      ;;
    --installation)
      INSTALLATION=1
      ;;
    --userspace)
      USERSPACE=1
      ;;
    --norootcheck)
      DISABLEROOTCHECK=1
      ;;
    *)
      echo "Unknown option '${ARG}'.  ${USAGE}." >&2
      exit 2
  esac
done

if [ "${USERSPACE}${INSTALLATION}" = "00" ]; then
  echo "${USAGE}."
  exit
fi

# this whole next part is because there's no readlink -f in Darwin
function readlinkf() {
  FINDFILE="$1"
  FILE="${FINDFILE}"
  PREVFILE=""
  C=0
  MAX=100 # just in case we end up in a loop
  FOUND=0
  while [ "${C}" -lt "${MAX}" -a "${FILE}" != "${PREVFILE}" -a "${FOUND}" -ne 1 ]; do
    PREVFILE="${FILE}"
    FILE="$(readlink "${FILE}")"
    if [ -z "${FILE}" ]; then
      # the readlink is empty means we've arrived at the script, let's canonicalize with pwd
      FILE="$(cd "$(dirname "${PREVFILE}")" &> /dev/null && pwd -P)"/"$(basename "${PREVFILE}")"
      FOUND=1
    elif [ "${FILE#/}" = "${FILE}" ]; then
      # FILE is not an absolute path link, we need to add the relative path to the previous dir
      FILE="$(dirname "${PREVFILE}")/${FILE}"
    fi
    C=$((C+1))
  done
  if [ "${FOUND}" -ne 1 ]; then
    echo "Could not determine path to actual file '$(basename "${FINDFILE}")'" >&2
    exit 1
  fi
  echo "${FILE}"
}

# args for the JVM
declare -a JVMARGS=()

# set vars for being inside the macos App Bundle
if [ "${ISMACOS}" = 1 ]; then
# MACOS ONLY
  SCRIPT="$(readlinkf "$0")"
  DIR="$(dirname "${SCRIPT}")"
  APPDIR="${DIR%/bin}"
  JAVABIN="${APPDIR}/jre/Contents/Home/bin"
  # e.g. APPFOLDER=/Applications/Jalview.app
  APPFOLDER="${APPDIR%%.app/*}.app"
  VMOPTIONS="${APPFOLDER}/Contents/vmoptions.txt"
else
# NOT MACOS
  SCRIPT="$(readlink -f "$0")"
  DIR="$(dirname "${SCRIPT}")"
  APPDIR="${DIR%/bin}"
  JAVABIN="${APPDIR}/jre/bin"
  # e.g. APPFOLDER=/opt/jalview
  APPFOLDER="${APPDIR}"
  VMOPTIONS="${APPDIR}/jalviewg.vmoptions"
fi
JAVA="${JAVABIN}/java"

# headless java arguments
JVMARGS=( "${JVMARGS[@]}" "-Djava.awt.headless=true" )
if [ "${ISMACOS}" = 1 ]; then
  JVMARGS=( "${JVMARGS[@]}" "-Dapple.awt.UIElement=true" )
fi

SYSJAVA=java
GETDOWNLAUNCHERJAR="${APPDIR}/getdown-launcher.jar"
GETDOWNCOREJAR="${APPDIR}/resource/getdown-core.jar"
CHANNELPROPS="${APPDIR}/channel.props"
NAME="$( grep app_name= "${CHANNELPROPS}" | cut -d= -f2 )"
US_NAME="${NAME// /_}"

GDL_CLASSPATH=""
GDC_CLASSPATH=""
# save an array of JAR paths in case we're in WSL (see later)
declare -a GDL_JARPATHS=()
declare -a GDC_JARPATHS=()
declare -a GDL_ARGS=()

# getdown-launcher classpath
if [ -e "${GETDOWNLAUNCHERJAR}" ]; then
  GDL_CLASSPATH="${GETDOWNLAUNCHERJAR}"
  GDL_JARPATHS=( "${GDL_JARPATHS[@]}" "${GETDOWNLAUNCHERJAR}" )
else
  echo "Cannot find ${GETDOWNLAUNCHERJAR} to run update" >&2
  exit 3
fi

# getdown-core classpath
if [ -e "${GETDOWNCOREJAR}" ]; then
  GDC_CLASSPATH="${GETDOWNCOREJAR}"
  GDC_JARPATHS=( "${GDC_JARPATHS[@]}" "${GETDOWNCOREJAR}" )
else
  echo "Cannot find $( basename "${GETDOWNCOREJAR}" ) to run update" >&2
  exit 4
fi

# USER space update
if [ "${USERSPACE}" = 1 ]; then
  if [ -e "${VMOPTIONS}" ]; then
    LINENUM=0
    while IFS= read -r line; do
      # remove comments
      line=${line%%#*}
      # remove leading and trailing whitespace
      line="${line%"${line##*[![:space:]]}"}"
      line="${line#"${line%%[![:space:]]*}"}"
      LINENUM=$((LINENUM+1))

      # add settings for user appdir
      if [ "${line}" != "${line#-Dsetuserappdirpath=}" ]; then # starts with -Dsetuserappdirpath=
        JVMARGS=( "${JVMARGS[@]}" "${line}" )
      fi
      if [ "${line}" != "${line#-Dnouserdefaultappdir=}" ]; then # starts with -Dnouserdefaultappdir=
        # don't perform user update if user updates are disabled
        NOUSERUPDATEVALUE="$(echo "${line#-Dnouserdefaultappdir=}" | tr '[:upper:]' '[:lower:]')"
        if [ "${NOUSERUPDATEVALUE}" = "true" ]; then
          echo "Cannot perform manual user-space update when user-space updates are disabled." >&2
          echo "See line ${LINENUM} (${line}) in file '${VMOPTIONS}'." >&2
          exit 5
        fi
        JVMARGS=( "${JVMARGS[@]}" "${line}" )
      fi
    done < "${VMOPTIONS}"
  fi
  JVMARGS=( "${JVMARGS[@]}" "-Duserdefaultappdir=true" )
  JVMARGS=( "${JVMARGS[@]}" "-Dnouserdefaultappdir=false" )
fi

# INSTALLATION update
if [ "${INSTALLATION}" = 1 ]; then
  # root permissions check
  if [ "${DISABLEROOTCHECK}" != 1 -a "${EUID}" != 0 ]; then
    echo "--installation updates should be run with root permissions, or disable this root check with --norootcheck" >&2
    exit 6
  fi
  JVMARGS=( "${JVMARGS[@]}" "-Duserdefaultappdir=false" )
  JVMARGS=( "${JVMARGS[@]}" "-Dnouserdefaultappdir=true" )
  JVMARGS=( "${JVMARGS[@]}" "-Dlauncher.appdir=${APPDIR}" )
  JVMARGS=( "${JVMARGS[@]}" "-Dappdir=${APPDIR}" )
fi

# setting the appdir arg[0] and appid arg[1] to blank values
# so appDir is determined by EnvConfig.getUserAppdir() or appdir property
# and appId is passed as system property appid
GDL_ARGS=( "" "" )

# both USER and INSTALLATION updates
JVMARGS=( "${JVMARGS[@]}" "-Dinstaller.appdir=${APPDIR}" )
JVMARGS=( "${JVMARGS[@]}" "-Dinstaller.application_folder=${US_NAME}" )
JVMARGS=( "${JVMARGS[@]}" "-Dlauncher.script=${SCRIPT}" )
JVMARGS=( "${JVMARGS[@]}" "-Dlauncher.update=true" )
JVMARGS=( "${JVMARGS[@]}" "-Dchannel.app_name=${NAME}" )
JVMARGS=( "${JVMARGS[@]}" "-Dappid=jalview" )

# IMPORTANT! tell getdown to update jalview withouth launching
JVMARGS=( "${JVMARGS[@]}" "-Dsilent=true" )

# add these Just In Case although jalview shouldn't be launched due to -Dsilent=true
GDL_ARGS=( "${GDL_ARGS[@]}" "--headless" "--quit" "--nojavaconsole" "--nosplash" "--nonews" )

# WINDOWS ONLY in Cygwin or Windows Subsystem for Linux (WSL)
# change paths for Cygwin or WSL
if [ "${ISMACOS}" != 1 ]; then # older macos doesn't like uname -o, best to avoid
  if [ "$(uname -o)" = "Cygwin" ]; then
    # CYGWIN
    GDL_CLASSPATH=$(cygpath -pw "${GDL_CLASSPATH}")
    GDC_CLASSPATH=$(cygpath -pw "${GDC_CLASSPATH}")
  elif uname -r | grep -i microsoft | grep -i wsl >/dev/null; then
    # WSL
    GDL_CLASSPATH=""
    for JARPATH in "${GDL_JARPATHS[@]}"; do
      [ -n "${GDL_CLASSPATH}" ] && GDL_CLASSPATH="${GDL_CLASSPATH};"
      GDL_CLASSPATH="${GDL_CLASSPATH}$(wslpath -aw "${JARPATH}")"
    done
    GDC_CLASSPATH=""
    for JARPATH in "${GDC_JARPATHS[@]}"; do
      [ -n "${GDC_CLASSPATH}" ] && GDC_CLASSPATH="${GDC_CLASSPATH};"
      GDC_CLASSPATH="${GDC_CLASSPATH}$(wslpath -aw "${JARPATH}")"
    done
    JAVA="${JAVA}.exe"
    SYSJAVA="java.exe"
  fi
fi

# Is there a bundled Java?  If not just try one in the PATH (we need .exe in WSL, added above)
if [ \! -e "${JAVA}" ]; then
  JAVA=$SYSJAVA
  echo "Cannot find bundled ${JAVA}, using system ${SYSJAVA} and hoping for the best!" >&2
fi

# This is just needed for display purposes
function quotearray() {
  QUOTEDVALS=""
  for VAL in "${@}"; do
    if [ \! "$QUOTEDVALS" = "" ]; then
      QUOTEDVALS="${QUOTEDVALS} "
    fi
    QUOTEDVALS="${QUOTEDVALS}\"${VAL}\""
  done
  echo $QUOTEDVALS
}

JVMARGSSTR=$(quotearray "${JVMARGS[@]}")
ARGSSTR=$(quotearray "${GDL_ARGS[@]}")

if [ "${DEBUG}" = 1 ]; then
 echo Shell running: \""${JAVA}"\" ${JVMARGSSTR} -cp \""${GDL_CLASSPATH}"\" com.threerings.getdown.launcher.GetdownApp ${ARGSSTR} >&2
fi

"${JAVA}" "${JVMARGS[@]}" -cp "${GDL_CLASSPATH}" com.threerings.getdown.launcher.GetdownApp "${GDL_ARGS[@]}"

# move updated getdown-launcher.jar into place
if [ "${DEBUG}" = 1 ]; then
  echo Shell running: \""${JAVA}"\" ${JVMARGSSTR} -cp \""${GDC_CLASSPATH}"\" jalview.bin.GetdownLauncherUpdate >&2
fi

"${JAVA}" "${JVMARGS[@]}" -cp "${GDC_CLASSPATH}" jalview.bin.GetdownLauncherUpdate
