#!/bin/bash

source $(dirname $0)/shared-run

getDiagnosticSessionRedirection()
{
   if [[ -n "${VSCODE_DIAGNOSTICS_ENABLED}" ]]; then
      echo "|& tee -a $VSCODE_DIAGNOSTICS_FILE"
   else
      echo ""
   fi
}

getDiagnosticsPrintenv()
{
   if [[ -n "${VSCODE_DIAGNOSTICS_ENABLED}" ]]; then
      echo "echo -e \"[$(date)] ---- launching vscode process ----\n[$(date)] ---- final env ----\n[$(date)] $(printenv)\" $(getDiagnosticSessionRedirection) &&"
   else
      echo ""
   fi
}

emitDiagnostic()
{
   if [[ -n "${VSCODE_DIAGNOSTICS_ENABLED}" ]]; then
      if ! echo "[$(date)] $1" >> $VSCODE_DIAGNOSTICS_FILE ; then
         echo "Error: $$ trying to append to $VSCODE_DIAGNOSTICS_FILE - turning off session diagnostics"
         VSCODE_DIAGNOSTICS_ENABLED=
      fi
   fi
}

getDiagnosticSessionStraceEnabled()
{
   if [[ -z "${VSCODE_DIAGNOSTICS_STRACE_ENABLED}" ]]; then
      echo "strace not enabled for this diagnostics report"
   elif command -v strace &> /dev/null; then
      echo "strace enabled for this diagnostics report"
      echo "strace report location: $VSCODE_STRACE_FILE"
      echo ""
   else
      echo "strace is not installed; cannot generate strace diagnostics"
   fi
}

getDiagnosticSessionStrace()
{
   if [[ -z "${VSCODE_DIAGNOSTICS_STRACE_ENABLED}" ]]; then
      echo ""
   elif command -v strace &> /dev/null; then
      echo "strace -fttTy -o $VSCODE_STRACE_FILE"
   else
      echo ""
   fi
}


runHooks "start"

# determine the config directory
if [ "$RSTUDIO_CONFIG_DIR" != "" ] ; then
   configDirs="$RSTUDIO_CONFIG_DIR"
else
   configDirs="$XDG_CONFIG_DIRS:/etc"
fi

IFS=':' read -ra configDirList <<< "$configDirs"
for configDir in "${configDirList[@]}"
do
   if test -e "$configDir/rstudio/vscode.conf"
   then
      configFile="$configDir/rstudio/vscode.conf"
      break
   fi
done

# load vscode-profile script
if test -e "$configDir/rstudio/vscode-profile"
then
   . "$configDir/rstudio/vscode-profile"
fi

# session arguments
# escape backslashes in arguments to pass safely to bash below
# escape twice as we are using eval
VSCODE_ARGS="${@//\\/\\\\\\\\}"
# eval variables like $USER that might be in --user-data-dir
VSCODE_ARGS=$(eval "echo $VSCODE_ARGS")

RS_VSCODE_USER_EXT=${RS_VSCODE_USER_EXT:-0}

# eval variables like $USER in XDG_DATA_HOME and XDG_STATE_HOME
XDG_DATA_HOME=$(eval echo $XDG_DATA_HOME)
XDG_STATE_HOME=$(eval echo $XDG_STATE_HOME)

USER_DATA_HOME=${XDG_DATA_HOME:-${HOME}/.local/share}

# Allow individual users to enable session diagnostics to their local log directory
USER_DIAG_CONFIG="$HOME/.config/pwb/vscode-diagnostics"
USER_DIAG_LOG_DIR="$USER_DATA_HOME/pwb/log"
if [[ -f "$USER_DIAG_CONFIG" ]] ; then
   USER_DIAG_MODE=$(cat "$USER_DIAG_CONFIG")
   if [[ "$USER_DIAG_MODE" =~ debug|strace ]] ; then
      export VSCODE_DIAGNOSTICS_ENABLED=true
      mkdir -p "$USER_DIAG_LOG_DIR"
      export VSCODE_DIAGNOSTICS_FILE="$USER_DIAG_LOG_DIR/vscode-diagnostics.log"
      VSCODE_STRACE_FILE="${VSCODE_DIAGNOSTICS_FILE}.strace"
      if [[ "$USER_DIAG_MODE" = "strace" ]] ; then
         export VSCODE_DIAGNOSTICS_STRACE_ENABLED=true
      fi
      if [[ "$VSCODE_EXEC_COMMAND" =~ .*pwb-code-server* ]] ; then
         LOG_PATTERN="--log"
         LOG_ARG="--log trace"
         # extract the --user-data-dir argument from VSCODE_ARGS
         USER_DATA_DIR=$(echo $VSCODE_ARGS | grep -oP -- '--user-data-dir \K[^ ]*')
         if [[ -n "$USER_DATA_DIR" ]] ; then
            LOG_DIR="$USER_DATA_DIR/data/logs"
         else
            LOG_DIR="$HOME/.vscode-server/data/logs"
         fi
      fi

      if [[ ! "$VSCODE_ARGS" =~ .*"$LOG_PATTERN".* ]] ; then 
         VSCODE_ARGS="$VSCODE_ARGS $LOG_ARG"
      fi
      echo "Enabling $USER_DIAG_MODE diagnostics from config file $USER_DIAG_CONFIG" 
      echo "Diag files: $VSCODE_DIAGNOSTICS_FILE + .strace"
      echo "Debug logs: $LOG_DIR"
   elif [[ "$USER_DIAG_MODE" != "off" ]] ; then
      echo "Ignoring invalid session-diagnostics value: $USER_DIAG_MODE for file: $USER_DIAG_CONFIG - use one of strace, debug or off"
   fi
fi

# install extension
if [ $RS_VSCODE_USER_EXT -eq 1 ]
then
   if [ -f /usr/lib/rstudio-server/extras/scripts/install-vs-code-ext.sh ]
   then
      VSCODE_EXEC_COMMAND=$VSCODE_EXEC_COMMAND VSCODE_ARGS=$VSCODE_ARGS /usr/lib/rstudio-server/extras/scripts/install-vs-code-ext.sh
   else
     echo "Skipping VS Code extension updates because /usr/lib/rstudio-server/extras/scripts/install-vs-code-ext.sh was not found."
   fi
fi

if [[ -n "${RS_SESSION_SSL_CERT}" ]]; then
   if [[ -z "${RS_SESSION_SSL_CERT_KEY}" ]]; then
      echo "Error - public key without private key"
      exit 10
   fi

   CERT_DIR="/tmp/pwb-${USER}"
   mkdir -m 700 -p "${CERT_DIR}"

   CERT_ID=$(date +%s.%N)
   CERT_FILE="${CERT_DIR}/cert-${CERT_ID}.pem"
   KEY_FILE="${CERT_DIR}/key-${CERT_ID}.pem"
   rm -f ${CERT_FILE} ${KEY_FILE}
   (umask 077;
    echo "${RS_SESSION_SSL_CERT}" > "${CERT_FILE}";
    echo "${RS_SESSION_SSL_CERT_KEY}" > "${KEY_FILE}")
   VSCODE_ARGS="${VSCODE_ARGS} --cert ${CERT_FILE} --cert-key ${KEY_FILE}"
elif [[ -n "${RS_SESSION_SSL_CERT_PATH}" ]] ; then
   # eval variables like $HOME and $USER in RS_SESSION_CERT_PATH
   eval CERT_PATH=`echo ${RS_SESSION_SSL_CERT_PATH}`
   eval KEY_PATH=`echo ${RS_SESSION_SSL_CERT_KEY_PATH}`
   VSCODE_ARGS="${VSCODE_ARGS} --cert ${CERT_PATH} --cert-key ${KEY_PATH}"
fi

# dump user information
emitDiagnostic "---- user ---- "
emitDiagnostic "$(whoami)"

# dump initial environment
emitDiagnostic "---- init env ----"
emitDiagnostic "$(printenv)"

emitDiagnostic "Running session: ${VSCODE_EXEC_COMMAND} ${VSCODE_ARGS}"

echo "Running session: ${VSCODE_EXEC_COMMAND} ${VSCODE_ARGS}"

# SIGTERM is used to stop the session - so the hooks need to be run as a trap
trap 'runHooks "stop"' SIGTERM

# run the session
/bin/bash --login $VSCODE_PROFILE_OPTIONS -c "$(getDiagnosticsPrintenv) $(getDiagnosticSessionStrace) $VSCODE_EXEC_COMMAND $VSCODE_ARGS"

# store exit code of command
EXIT_CODE=$?

if [[ -n "${CERT_DIR}" ]]; then
   rm -f "${CERT_FILE}"
   rm -f "${KEY_FILE}"
fi

# exit with previously-stored exit code, after cleanup
exit $EXIT_CODE
