#!/usr/bin/env bash
# This script will install RStudio's VS Code extension.

set -e

s3_bucket=https://rsw-vscode-extension.s3.amazonaws.com
default_ext_version=1.1.7

while getopts d:lv: flag
do
    case "${flag}" in
        d) installDirectory=${OPTARG};;
        l) local=1;;
        v) ext_version=${OPTARG};
            if [[ ! "$ext_version" =~ ^([0-9]+.){2}[0-9]+$ ]]
            then
                echo 'error: invalid version '$ext_version' - expecting three numbers separated by periods\n';
                exit 1
            fi
    esac
done

# load and parse vscode config file
configDirs="$XDG_CONFIG_DIRS:/etc"
origIFS=$IFS
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
IFS=$origIFS

# exit if we cannot determine the vs code executable
if [ ! -f "$configFile" ]
then
   if [[ -z "$VSCODE_EXEC_COMMAND" ]]
   then
      if [ -z "$POST_INSTALL_SCRIPT" ]; then
         echo "ERROR: Could not install extension. The code-server executable must be set by VSCODE_EXEC_COMMAND or as exe in vscode.conf."
      fi
      exit 1
   else
      cs_exe=$VSCODE_EXEC_COMMAND
   fi
else
   cs_exe=$(grep exe $configFile | sed 's/.*\(exe=\)\(.[^ ]*\).*/\2/')
   ext_dir=$(grep 'extensions-dir[= ]' $configFile | sed 's/.*\(extensions-dir[= ]\)\(.[^ ]*\).*/\2/')
   if [ ! -z "$ext_dir" ] && [ ! -d "$ext_dir" ]
   then
      echo "$ext_dir does not exist - creating..."
      mkdir $ext_dir
   fi

   if [ -z "$ext_version" ]
   then
      ext_version=$(grep 'min-ext-version' $configFile | sed 's/.*\(min-ext-version=\)\(.[^ ]*\).*/\2/')
      if [[ ! -z "$ext_version" && ! "$ext_version" =~ ^([0-9]+.){2}[0-9]+$ ]]; then
        echo "WARNING: Invalid min-ext-version: expecting three numbers separated by periods, found $ext_version. Using $default_ext_version instead."
      fi
   fi
fi


echo "Starting VS Code management process..."

if [ -z "$ext_version" ]; then
  ext_version=$default_ext_version
fi
# Compare installed version of code-server with the recommended version
latestCodeServerVersion=3.12.0
latestCodeServerMajor=3
latestCodeServerMinor=12
latestCodeServerPatch=0

# compare installed version of code-server with the minimum required
minCodeServerVersion=3.9.3
minCodeServerMajor=3
minCodeServerMinor=9
minCodeServerPatch=3

# retrieve installed code-server version
codeServerVersion=$($cs_exe -v | grep -o '^[0-9]\+\.[0-9]\+\.[0-9]\+')
codeServerMajor=$(echo $codeServerVersion | sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\1/')
codeServerMinor=$(echo $codeServerVersion | sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\2/')
codeServerPatch=$(echo $codeServerVersion | sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)/\3/')

# check if upgrade required
if [[ -z "$codeServerVersion" || -z "$codeServerMajor" || -z "$codeServerMinor" || -z "$codeServerPatch" ]]
then
  echo "Warning: Could not parse code-server version. Required version is $minCodeServerVersion."
else
   if [[ $codeServerMajor -lt $minCodeServerMajor ]]; then
      needToUpgrade=1
   elif [[ $codeServerMajor -eq $minCodeServerMajor &&
           $codeServerMinor -lt $minCodeServerMinor ]]; then
      needToUpgrade=1
   elif [[ $codeServerMajor -eq $minCodeServerMajor &&
           $codeServerMinor -eq $minCodeServerMinor &&
           $codeServerPatch -lt $minCodeServerPatch ]]; then
      needToUpgrade=1
   fi

   if [[ $codeServerMajor -lt $latestCodeServerMajor ]]; then
      wantToUpgrade=1
   elif [[ $codeServerMajor -eq $latestCodeServerMajor &&
         $codeServerMinor -lt $latestCodeServerMinor ]]; then
      wantToUpgrade=1
   elif [[ $codeServerMajor -eq $latestCodeServerMajor &&
         $codeServerMinor -eq $latestCodeServerMinor &&
         $codeServerPatch -lt $latestCodeServerPatch ]]; then
      wantToUpgrade=1
   fi
fi


if [[ ! $installDirectory && $needToUpgrade -ne 1 && $wantToUpgrade -eq 1 ]]
then
   # warn that a newer version of code-server is recommended and then continue on
   1>&2 echo -e "\nWARNING RStudio Workbench VSCode Extension requires code-server to have newer" \
         "version than '$minCodeServerVersion' in order to esatablish secure SSL communication with the code-server session. " \
         "The recommended version of code-server is '$latestCodeServerVersion' and the current version is '$codeServerVersion'. " \
         "Run 'install-vs-code-ext' with '-d' and code-server's install directory to" \
         "upgrade code-server to '$latestCodeServerVersion' and install the extension.\n"
fi

if [[ $installDirectory || $needToUpgrade -eq 1 ]]
then
   if [ -z $installDirectory ]
   then
      # warn and exit if upgrade code-server is required
      1>&2 echo -e "\nWARNING RStudio Workbench VSCode Extension requires code-server to have a" \
            "minimum version of '$minCodeServerVersion', and the current version is '$codeServerVersion'. " \
            "The recommended version of code-server is '$latestCodeServerVersion'. " \
            "Run 'install-vs-code-ext' with '-d' and code-server's install directory to" \
            "upgrade code-server to '$latestCodeServerVersion' and install the extension.\n"
         exit 1
   fi

   # upgrade code-server
   echo "Upgrading code-server ..."

   # clean up old version, unsure why this is necessary but otherwise extensions do not install
   if [[ -e $(dirname $cs_exe)/lib/vscode/node_modules ]]
   then
      rm -rf $(dirname $cs_exe)/lib/vscode/node_modules
   fi

   codeServerTar="vs-code-server-${latestCodeServerVersion}.tar.gz"
   curl -L "${s3_bucket}/code-server/code-server-${latestCodeServerVersion}-linux-amd64.tar.gz" -o "/tmp/${codeServerTar}"
   tar zxvf "/tmp/${codeServerTar}" --strip 1 -C "$installDirectory"
   rm "/tmp/${codeServerTar}"

   # code-server removed the --disable-updates flag in 3.3.0 and moved the executable to /bin
   if [[ $codeServerMajor -lt 3 ]] ||
      [[ $codeServerMajor -eq 3  && $codeServerMinor -lt 3 ]]
   then
      orig_cs_exe="$cs_exe"
      cs_exe=$(dirname $cs_exe)/bin/code-server
      sed -i "s|$orig_cs_exe|$cs_exe|" $configFile
      sed -iE "s|--disable-updates[ ]\?||" $configFile
   fi
fi

# download the extension to the current user's directory
if [[ $local -eq 1 ]]
then
   echo "RStudio Workbench VS Code extension $ext_version will be installed for $USER."

   if [ ! -z "$RSTUDIO_DATA_HOME" ]; then
      userDirectory=$RSTUDIO_DATA_HOME
   elif [ ! -z "$XDG_DATA_HOME" ]; then
      userDirectory=$XDG_DATA_HOME/rstudio
   else
      userDirectory=$HOME/.local/share/rstudio
   fi

   if [ ! -d "$userDirectory" ]; then
      echo "ERROR: Could not determine data directory for $USER. RStudio Workbench VS Code extension not installed."
      exit 1
   fi

   subDirectory=vscode-extensions
   if [ ! -d "$userDirectory/$subDirectory" ]
   then
      echo "$userDirectory/$subDirectory does not exist - creating..."
      mkdir $userDirectory/$subDirectory
   fi

   # download the extension
   if [ -f "$userDirectory/$subDirectory/rstudio-workbench-$ext_version.vsix" ]
   then
      echo -e "\nExtension already downloaded, skipping download ...\n"
   else
      echo -e "\nDownloading the RStudio Workbench VS Code extension ...\n"
      curl -L "${s3_bucket}/rstudio-workbench-$ext_version.vsix" -o "$userDirectory/$subDirectory/rstudio-workbench-$ext_version.vsix"
   fi

   # install the extension
   echo "Installing the RStudio Workbench VS Code extension ..."
   $cs_exe --install-extension $userDirectory/$subDirectory/rstudio-workbench-$ext_version.vsix
   exit 0
fi

# download the extension to the global extensions directory
if [ $ext_dir ]
then
   # download the extension
   echo "RStudio Workbench VS Code extension $ext_version will be installed at $ext_dir..."
   if [ -f "$ext_dir/rstudio-workbench-$ext_version.vsix" ]
   then
      echo -e "\nExtension already downloaded, skipping download ...\n"
   else
      echo -e "\nDownloading the RStudio Workbench VS Code extension ...\n"
      curl -L "${s3_bucket}/rstudio-workbench-$ext_version.vsix" -o "$ext_dir/rstudio-workbench-$ext_version.vsix"
   fi

   # install extension
   echo "Installing the RStudio Workbench VS Code extension ..."
   "$cs_exe" --extensions-dir "$ext_dir" --install-extension "$ext_dir/rstudio-workbench-$ext_version.vsix"
   exit 0
fi
