#!/usr/bin/env bash
#
# This is the spinalcord toolbox (SCT) installer
# It downloads the Conda (http://conda.pydata.org/) version
# of python and installs the SCT requirements over it
#
# The SCT can be installed in the location where you download it. If you choose to do so,
# do not delete the source code or you will delete the installation too!
#
# If you run the installer as super user, the default install is /opt,
# if you choose this option or any other directory other than the
# source location, you can get rid of the source code after the
# installation is successful.
#
# USAGE
#   ./install_sct [-h] [-i] [-y] [-d] [-b] [-v]
#
# OPTIONS
#  -h   Show this help
#  -i   Install in-place; this is the default when working from git.
#  -y   Install without interruption with 'yes' as default answer
#  -d   Prevent the (re)-installation of the data/ directory
#  -b   Prevent the (re)-installation of the SCT binaries files
#  -c   Prevent checks from being run to validate the installation
#  -v   Full verbose
#
#
# Copyright (c) 2019 Polytechnique Montreal <www.neuro.polymtl.ca>
# Authors: PO Quirion, J Cohen-Adad, J Carretero
# License: see the file LICENSE.TXT

# Change directory to where the script is, for the duration of the script.
# This lives outside the subshell below to guarantee the corresponding
# popd gets run, no matter how the installation script exits.
pushd -- "${BASH_SOURCE[0]%/*}/" >/dev/null || exit 1

( # | tee install_sct_log.txt

# stricter shell mode
# https://sipb.mit.edu/doc/safe-shell/
set -eo pipefail  # exit if non-zero error is encountered (even in a pipeline)
set -u            # exit if unset variables used
shopt -s failglob # error if a glob doesn't find any files, instead of remaining unexpanded

# set -v  # v: verbose

# Where tmp file are stored
TMP_DIR="$(mktemp -d 2>/dev/null || mktemp -d -t 'TMP_DIR')"
SCT_SOURCE="$PWD"
DATA_DIR="data"
PYTHON_DIR="python"
BIN_DIR="bin"
MACOSSUPPORTED="13"  # Minimum version of macOS 10 supported

# CLI options
SCT_INSTALL_TYPE=""
NONINTERACTIVE=""
NO_DATA_INSTALL=""
NO_SCT_BIN_INSTALL=""
NO_INSTALL_VALIDATION=""

# ======================================================================================================================
# FUNCTIONS
# ======================================================================================================================

# Print with color
# @input1: {info, code, error}: type of text
# rest of inputs: text to print
function print() {
  type=$1; shift
  case "$type" in
  # Display useful info (green)
  info)
    echo -e "\n\033[0;32m${*}\033[0m\n"
    ;;
  # To interact with user (no carriage return) (light green)
  question)
    echo -e -n "\n\033[0;92m${*}\033[0m"
    ;;
  # To display code that is being run in the Terminal (blue)
  code)
    echo -e "\n\033[0;34m${*}\033[0m\n"
    ;;
  # Warning message (yellow)
  warning)
    echo -e "\n\033[0;93m${*}\033[0m\n"
    ;;
  # Error message (red)
  error)
    echo -e "\n\033[0;31m${*}\033[0m\n"
    ;;
  esac
}

# Elegant exit with colored message
function die() {
  print error "$1"
  exit 1
}

# Run a command and display it in color. Exit if error.
# @input: string: command to run
function run() {
  ( # this subshell means the 'die' only kills this function and not the whole script;
    # the caller can decide what to do instead (but with set -e that usually means terminating the whole script)
    print code "$@"
    if ! "$@" ; then
      die "ERROR: Command failed."
    fi
  )
}

# Force a clean exit
function finish() {
  # Catch the last return code
  value="$?"
  if [[ "$value" -eq 0 ]]; then
    print info "Installation finished successfully!"
  elif [[ "$value" -eq 99 ]]; then
    # Showing usage with -h
    echo ""
  else
    print error "Installation failed!\n
Please find the file \"$SCT_SOURCE/install_sct_log.txt\",
then upload it as a .txt attachment in a new topic on SCT's forum:
--> http://forum.spinalcordmri.org/c/sct"
  fi
  # clean tmp_dir
  rm -rf "$TMP_DIR"
  exit "$value"
}

# reenable tty echo when user presses keyboard interrupt and output non-zero status for finish() function
detectKeyboardInterrupt() {
      # reenable tty echo
      print error "Installation aborted by the user."
      stty icanon echo echok
      exit 1
}

# Fetches the OS type
# @output: OS var is modified with the appropriate OS
function fetch_os_type() {
  print info "Checking OS type and version..."
  OSver="unknown"  # default value
  uname_output="$(uname -a)"
  echo "$uname_output"
  # macOS
  if echo "$uname_output" | grep -i darwin >/dev/null 2>&1; then
    # Fetch macOS version
    sw_vers_output="$(sw_vers | grep -e ProductVersion)"
    echo "$sw_vers_output"
    OSver="$(echo "$sw_vers_output" | cut -c 17-)"
    macOSmajor="$(echo "$OSver" | cut -f 1 -d '.')"
    macOSminor="$(echo "$OSver" | cut -f 2 -d '.')"
    # Make sure OSver is supported
    if [[ "${macOSmajor}" = 10 ]] && [[ "${macOSminor}" < "${MACOSSUPPORTED}" ]]; then
      die "Sorry, this version of macOS (10.$macOSminor) is not supported. The minimum version is 10.$MACOSSUPPORTED."
    fi
    # Fix for non-English Unicode systems on MAC
    if [[ -z "${LC_ALL:-}" ]]; then
      export LC_ALL=en_US.UTF-8
    fi

    if [[ -z "${LANG:-}" ]]; then
      export LANG=en_US.UTF-8
    fi
    OS="osx"
    # make sure bashrc is loaded when starting a new Terminal
    force_bashrc_loading
  # Linux
  elif echo "$uname_output" | grep -i linux >/dev/null 2>&1; then
    OS="linux"
  else
    die "Sorry, the installer only supports Linux and macOS, quitting installer"
  fi
}

# Checks if the necessary tools for SCT are installed on the machine
function check_requirements() {
  print info "Checking requirements..."
  # check curl
  if [[ ! ( $(command -v curl) || $(command -v wget) ) ]]; then
    die "ERROR: neither \"curl\" nor \"wget\" is installed. Please install either of them and restart SCT installation."
  fi
  # check gcc
  if ! gcc --version > /dev/null 2>&1; then
    print warning "WARNING: \"gcc\" is not installed."
    if [[ "$OS" == "osx" ]]; then
      while [[ ! "$GCC_INSTALL" =~ ^([Yy](es)?|[Nn]o?)$ ]]; do
        GCC_INSTALL="no"
        if [ -z "$NONINTERACTIVE" ]; then
          print question "Do you want to install it now? (accepting to install \"gcc\" will also install \"brew\" in case it is not installed already)? [y]es/[n]o: "
          read -r GCC_INSTALL
        fi
      done
      if [[ "$GCC_INSTALL" =~ [Yy](es)? ]]; then
        if [[ ! $(command -v brew) ]]; then
          # NB: this is a different NONINTERACTIVE than ours above; it's for the brew installer
          (NONINTERACTIVE=1 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)")
        fi
        brew install -f gcc
        # check if gcc install ran properly
        if ! gcc --version > /dev/null 2>&1; then
          die "ERROR: Installation of \"gcc\" failed. Please contact SCT team for assistance."
        fi
      else
        die "Please install \"gcc\" and restart SCT installation."
      fi
    else
      die "Please install \"gcc\" and restart SCT installation. On Debian/Ubuntu, run: \"apt install gcc\". On CentOS/RedHat, run: \"yum -y install gcc\"."
    fi
  fi
  print info "OK!"
}

# Gets the shell rc file path based on the default shell.
# @output: THE_RC and RC_FILE_PATH vars are modified
function get_shell_rc_path() {
  if [[ "$SHELL" == *"bash"* ]]; then
    THE_RC="bash"
    RC_FILE_PATH="$HOME/.bashrc"
  elif [[ "$SHELL" == *"/sh"* ]]; then
    THE_RC="bash"
    RC_FILE_PATH="$HOME/.bashrc"
  elif [[ "$SHELL" == *"zsh"* ]]; then
    THE_RC="bash"
    RC_FILE_PATH="$HOME/.zshrc"
  elif [[ "$SHELL" == *"csh"* ]]; then
    THE_RC="csh"
    RC_FILE_PATH="$HOME/.cshrc"
  else
    find ~/.* -maxdepth 0 -type f
    die "ERROR: Shell was not recognized: $SHELL"
  fi
}

# Force bashrc loading
function force_bashrc_loading() {
  sourceblock="
if [[ -n \"\$BASH_VERSION\" ]]; then
    # include .bashrc if it exists
    if [[ -f \"\$HOME/.bashrc\" ]]; then
    . \"\$HOME/.bashrc\"
    fi
fi"
  bidon=""
  for profile in ~/.bash_profile ~/.bash_login ~/.profile; do
    if [[ -a "$profile" ]]; then
      if ! grep -E "(\.|source) .*bashrc" "$profile" >/dev/null 2>&1; then
        echo "$sourceblock" >>"$profile"
      fi
      bidon="done"
      break
    fi
  done

  if [[ -z "$bidon" ]]; then
    echo "$sourceblock" >>~/.bash_profile
  fi
}

# Installation text to insert in shell config file
function edit_shellrc() {
  # Write text common to all shells
  (
    echo
    echo ""
    echo "# SPINALCORDTOOLBOX (installed on $(date +%Y-%m-%d\ %H:%M:%S))"
    echo "$DISPLAY_UPDATE_PATH"
    # Switch between shell
    if [[ "$THE_RC" == "bash" ]]; then
      echo "export SCT_DIR=$SCT_DIR"
    elif [[ "$THE_RC" == "csh" ]]; then
      echo "setenv SCT_DIR $SCT_DIR"
    fi
    # add line
    echo ""
  ) >> "$RC_FILE_PATH"
}

# Download from URL using curl/wget
function download() {
  ( (command -v wget >/dev/null) && run wget -nv -O "$1" "$2" ) ||
  ( (command -v curl >/dev/null) && run curl -sS -o "$1" -L "$2" ) ||
  die "The download of $2 failed
Please check that you have wget or curl installed, and
your internet connection before relaunching the installer"
}

# Usage of this script
function usage() {
  # extract the usage block from our own header
  awk '
    BEGIN {
      printing=0
      blanks=0
    }

    # filter for block-comments
    $0 !~ /^#/   { next }
    # but strip any leading "# "
                 { sub("^#[[:space:]]?","") }

    # count consecutive blank lines
    # so we can detect the section break
    /^$/         { blanks++ }
    $0 !~ /^$/   { blanks=0 }

    # detect usage section
    /USAGE/      { printing=1 }
    printing==1  { print }
    (printing==1 && blanks>=2) { exit }
  ' "$0"
}

if [ "$(uname)" = "Darwin" ]; then
  # macOS polyfills

  # Linux has `realpath` and `readlink -f`.
  # BSD has `readlink -f`.
  # macOS has neither: https://izziswift.com/how-can-i-get-the-behavior-of-gnus-readlink-f-on-a-mac/
  # even though it *has* the function in its libc: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/realpath.3.html
  # Someone even wrote a whole C program just for this: https://github.com/harto/realpath-osx/.
  # https://stackoverflow.com/a/3572105 suggests some bash trickery but it
  # seems pretty fragile and that it probably doesn't actually expand symlinks.
  # So here, solve it with python. It's not great either, but since much of
  # this script already is just calling python at least it's reliable.
  (command -v realpath >/dev/null) || realpath() {
    python3 -c 'import sys, os; [print(os.path.realpath(f)) for f in sys.argv[1:]]' "$@"
  }
fi

# ======================================================================================================================
# SCRIPT STARTS HERE
# ======================================================================================================================

# ----------------------------------------------------------------------------------------------------------------------
# CLI parser
# ----------------------------------------------------------------------------------------------------------------------

# Transform  long option "--long" into short option  "-l"
for arg in "$@"; do
  shift
  case "$arg" in
    *)       set -- "$@" "$arg"
  esac
done

while getopts ":iydbcvh" opt; do
  case $opt in
  i)
    SCT_INSTALL_TYPE="in-place"
    ;;
  y)
    echo " non-interactive mode"
    NONINTERACTIVE="yes"
    ;;
  d)
    echo " data directory will not be (re)-installed"
    NO_DATA_INSTALL="yes"
    ;;
  b)
    echo " SCT binaries will not be (re)-installed "
    NO_SCT_BIN_INSTALL="yes"
    ;;
  c)
    echo " no checks will be run (installation will not be validated)"
    NO_INSTALL_VALIDATION="yes"
    ;;
  v)
    echo " Full verbose!"
    set -x
    ;;
  h)
    usage
    exit 0
    ;;
  *)
    usage
    exit 99
    ;;
  esac
done


# ----------------------------------------------------------------------------------------------------------------------
# Prepare installation
# ----------------------------------------------------------------------------------------------------------------------

# This trap specifically catches keyboardInterrupt and output a non-zero status before running finish()
trap detectKeyboardInterrupt INT
# Set a trap which, on shell error or shell exit, runs finish()
trap finish EXIT

print info "
*******************************
* Welcome to SCT installation *
*******************************
"

fetch_os_type
check_requirements

# Catch SCT version
if [[ -e "spinalcordtoolbox/version.txt" ]]; then
  SCT_VERSION="$(cat spinalcordtoolbox/version.txt)"
else
  die "ERROR: version.txt not found."
fi

# Get installation type (from git or from package) if not already specified
if [[ -z "$SCT_INSTALL_TYPE" ]]; then
  # The file 'requirements-freeze.txt` only exists on the `release` branch
  # or in stable release "Source Code" .zips (which point at tags `release`)
  if [[ -e "requirements-freeze.txt" ]]; then
    SCT_INSTALL_TYPE="package"   # i.e. release installations
  else
    SCT_INSTALL_TYPE="in-place"  # i.e. dev installations
  fi
fi

# Define sh files
get_shell_rc_path

# Display install info
echo -e "\nSCT version ......... $SCT_VERSION"
echo -e "Installation type ... $SCT_INSTALL_TYPE"
echo -e "Operating system .... $OS ($OSver)"
echo -e "Shell config ........ $RC_FILE_PATH"

REPORT_STATS="no"
if [ -z "$NONINTERACTIVE" ]; then
  # Send crash statistic and error logs to developers, that is the question:
  print question "To improve user experience and fix bugs, the SCT development team is using a
report system to automatically receive crash reports and errors from users.
These reports are anonymous.

Do you agree to help us improve SCT? [y]es/[n]o: "
  read -r REPORT_STATS
fi

if [[ "$REPORT_STATS" =~ [Yy](es)? ]]; then
  echo -ne '# Auto-generated by install_sct\nimport os\nSENTRY_DSN=os.environ.get("SCT_SENTRY_DSN", "https://5202d7c96ad84f17a24bd2653f1c4f9e:c1394bb176cc426caf0ff6a9095fb955@sentry.io/415369")\n' >spinalcordtoolbox/sentry_dsn.py
  print info "--> Crash reports will be sent to the SCT development team. Thank you!"
else
  print info "--> Crash reports will not be sent."
fi

# if installing from git folder, then becomes default installation folder
if [[ "$SCT_INSTALL_TYPE" == "in-place" ]]; then
  SCT_DIR="$SCT_SOURCE"
else
  SCT_DIR="$HOME/sct_$SCT_VERSION"
fi

# Set install dir
while true; do
  keep_default_path=""
  while [[ ! "$keep_default_path" =~ ^([Yy](es)?|[Nn]o?)$ ]]; do
    print info "SCT will be installed here: [$SCT_DIR]"
    keep_default_path="yes"
    if [ -z "$NONINTERACTIVE" ]; then
      print question "
Do you agree? [y]es/[n]o: "
      read -r keep_default_path
    fi
  done
  if [[ "$keep_default_path" =~ ^[Yy] ]]; then
    # user accepts default path --> exit loop
    break
  fi

  # ASSUMPTION: the rest of these are not guarded by $NONINTERACTIVE because this loop should have been broken already in that case.

  print question "Choose install directory. Warning! Give full path (e.g. /usr/django/sct_v3.0): \n"
  # user enters new path
  read -r new_install

  # Expand ~/
  new_install="${new_install/#\~\//$HOME\/}"
  # Remove trailing /
  new_install="${new_install%/}"

  # Avoid horrible bug, like removing /bin if SCT_DIR "/" or $HOME/bin
  if [[ "$new_install" == "/" ]] || [[ "$HOME" == "${new_install%/}" ]]; then
    print info "Cannot be installed directly in $new_install"
    print info "Please pick a full path"
    continue
  elif [[ -d "$new_install" ]]; then
    # directory exists --> update SCT_DIR and exit loop
    print warning "WARNING: Directory already exists. Files will be overwritten."
    SCT_DIR="$new_install"
    break
  elif [[ ! "$new_install" ]]; then
    # If no input, asking again, and again, and again
    continue
  else
    SCT_DIR="$new_install"
    break
  fi
done

space_regex="[[:space:]]+"
if [[ $SCT_DIR =~ $space_regex ]]; then
  die "ERROR: Install directory $SCT_DIR contains spaces.\n\
       SCT uses conda, which does not permit spaces in installation paths.\n\
       More details can be found here: https://github.com/ContinuumIO/anaconda-issues/issues/716"
fi

# update PATH environment?
add_to_path=""
while [[ ! "$add_to_path" =~ ^([Yy](es)?|[Nn]o?)$ ]]; do
  add_to_path="yes"
  if [ -z "$NONINTERACTIVE" ]; then
    print question "Do you want to add the sct_* scripts to your PATH environment? [y]es/[n]o: "
    read -r add_to_path
  fi
done

# Create directory
mkdir -p "$SCT_DIR"
# check if directory was created
if [[ -d "$SCT_DIR" ]]; then
  # check write permission
  if [[ ! -w "$SCT_DIR" ]]; then
    die "ERROR: $SCT_DIR exists but does not have write permission."
  fi
else
  die "ERROR: $SCT_DIR cannot be created. Make sure you have write permission."
fi

# Update PATH variables based on Shell type
if [[ $THE_RC == "bash" ]]; then
  DISPLAY_UPDATE_PATH="export PATH=\"$SCT_DIR/$BIN_DIR:\$PATH\""
elif [[ $THE_RC == "csh" ]]; then
  DISPLAY_UPDATE_PATH="setenv PATH \"$SCT_DIR/$BIN_DIR:\$PATH\""
else
  die "This variable is not recognized: THE_RC=$THE_RC"
fi

# Copy files to destination directory
if [[ "$SCT_DIR" != "$SCT_SOURCE" ]]; then
  print info "Copying source files from $SCT_SOURCE to $SCT_DIR"
  cp -vR "$SCT_SOURCE/"* "$SCT_DIR/" | while read -r; do echo -n "."; done
else
  print info "Skipping copy of source files (source and destination folders are the same)"
fi

# Clean old install setup in bin/ if existing
if [[ -x "$SCT_DIR/$BIN_DIR" ]]; then
  print info "Removing sct and isct softlink from $SCT_DIR/$BIN_DIR"
  find "$SCT_DIR/$BIN_DIR" -type l -name 'sct_*' -exec rm {} \;
  find "$SCT_DIR/$BIN_DIR" -type l -name 'isct_*' -exec rm {} \;
fi

# Go to installation folder
cd "$SCT_DIR"

# Make sure we are in SCT folder (to avoid deleting folder from user)
if [[ ! -f "spinalcordtoolbox/version.txt" ]]; then
  die "ERROR: Cannot cd into SCT folder. SCT_DIR=$SCT_DIR"
fi


# ----------------------------------------------------------------------------------------------------------------------
# Install Python
# ----------------------------------------------------------------------------------------------------------------------


# Remove old python folder
run rm -rf "$SCT_DIR/$PYTHON_DIR"
run mkdir -p "$SCT_DIR/$PYTHON_DIR"

# Download miniconda
print info "Downloading Miniconda..."
case $OS in
linux*)
  download "$TMP_DIR/"miniconda.sh https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh
  ;;
osx)
  download "$TMP_DIR/"miniconda.sh https://repo.anaconda.com/miniconda/Miniconda3-latest-MacOSX-x86_64.sh
  ;;
esac

# Run conda installer
print info "Installing Miniconda..."
run bash "$TMP_DIR/miniconda.sh" -p "$SCT_DIR/$PYTHON_DIR" -b -f

# Workaround for WSL "HTTP 000 Connection Failed" error
# See: https://github.com/conda/conda/issues/9948#issuecomment-909989810
# Syntax explanation: https://stackoverflow.com/a/6085237
find "$SCT_DIR/$PYTHON_DIR" -type f -exec touch {} +

# create conda environment
print info "Creating conda environment..."
python/bin/conda create -y -n venv_sct python=3.7

# Reapply the touch fix to avoid `pip` connection issues on WSL
find "$SCT_DIR/$PYTHON_DIR" -type f -exec touch {} +

# make sure that there is no conflict with local python install by making venv_sct an isolated environment.
# For more information, see:
# * Issue details: https://github.com/spinalcordtoolbox/spinalcordtoolbox/issues/3067
# * Fix details: https://github.com/conda/conda/issues/7173#issuecomment-980496682
echo "include-system-site-packages = false" > "$SCT_DIR/$PYTHON_DIR/envs/venv_sct/pyvenv.cfg"

# activate miniconda
# shellcheck disable=SC1091
source python/etc/profile.d/conda.sh
set +u #disable safeties, for conda is not written to their standard.
conda activate venv_sct
set -u # reactivate safeties

# double-check conda activated (it can be glitchy): https://github.com/spinalcordtoolbox/spinalcordtoolbox/issues/3029
print info "Validating that conda environment can be activated..."
EXPECTED_PYTHON="$(realpath "$(command -v python/envs/venv_sct/bin/python)")"
ACTUAL_PYTHON="$(realpath "$(command -v python)")"
if [ "$ACTUAL_PYTHON" != "$EXPECTED_PYTHON"  ]; then
  echo "Mismatch between expected and actual python!"
  pwd
  echo "Expected Python: $EXPECTED_PYTHON"
  echo "Actual Python: $ACTUAL_PYTHON"
fi

# Skip pip==21.2 to avoid dependency resolver issue (https://github.com/spinalcordtoolbox/spinalcordtoolbox/issues/3593)
python -m pip install -U "pip!=21.2.*"

## Install the spinalcordtoolbox into the Conda venv
print info "Installing Python dependencies..."
# Check if a frozen version of the requirements exist (for release only)
if [[ -f "requirements-freeze.txt" ]]; then
  print info "Using requirements-freeze.txt (release installation)"
  REQUIREMENTS_FILE="requirements-freeze.txt"
else
  # Not a package
  print info "Using requirements.txt (git installation)"
  REQUIREMENTS_FILE="requirements.txt"
fi
(
  # We use "--ignore-installed" to preserve the version of `certifi` installed into the conda
  # env, which prevents https://github.com/spinalcordtoolbox/spinalcordtoolbox/issues/3609
  pip install -r "$REQUIREMENTS_FILE" --ignore-installed certifi &&
  print info "Installing spinalcordtoolbox..." &&
  pip install -e .
) ||
  die "Failed running pip install: $?"

## Check if CPU supports AVX instruction set, and install precompiled TensorFlow if it isn't,
case $OS in
linux*)
  if ! lscpu | grep -q " avx "; then
    print info "AVX is not supported by this CPU! Installing a version of TensorFlow compiled for older CPUs..."
    pip uninstall tensorflow -y
    pip install https://github.com/spinalcordtoolbox/docker-tensorflow-builder/releases/download/v1.15.5-py3.7/tensorflow-1.15.5-cp37-cp37m-linux_x86_64.whl
  else
    print info "AVX is supported on this Linux machine. Keeping default TensorFlow..."
  fi
  ;;
osx)
  if sysctl machdep.cpu.brand_string | grep -q "Apple M1"; then
    print info "AVX is not supported on M1 Macs! Installing a version of TensorFlow compiled for M1 Macs..."
    pip uninstall tensorflow -y
    pip install https://github.com/spinalcordtoolbox/docker-tensorflow-builder/releases/download/v1.15.5-py3.7/tensorflow-1.15.0-py3-none-any.whl
  else
    print info "AVX is supported on this macOS machine. Keeping default TensorFlow..."
  fi
  ;;
esac

## Create launchers for Python scripts
print info "Creating launchers for Python scripts..."
mkdir -p "$SCT_DIR/$BIN_DIR"
for file in "$SCT_DIR"/python/envs/venv_sct/bin/*sct*; do
  cp "$file" "$SCT_DIR/$BIN_DIR/" || die "Problem creating launchers!"
done

# Activate the launchers, particularly sct_download_data and sct_check_requirements
export PATH="$SCT_DIR/$BIN_DIR:$PATH"

# ----------------------------------------------------------------------------------------------------------------------
# Download binaries and data
# ----------------------------------------------------------------------------------------------------------------------

# Install binaries
if [[ -n "$NO_SCT_BIN_INSTALL" ]]; then
  print warning "WARNING: SCT binaries will not be (re)-installed"
else
  print info "Installing binaries..."
  run sct_download_data -d "binaries_${OS}" -k
fi
print info "All requirements installed!"

# Install data
if [[ -n "$NO_DATA_INSTALL" ]]; then
  print warning "WARNING: data/ will not be (re)-install"
else
  # Download data
  print info "Installing data..."
  run rm -rf "$SCT_DIR/$DATA_DIR"
  run mkdir -p "$SCT_DIR/$DATA_DIR"
  for data in PAM50 gm_model optic_models pmj_models deepseg_sc_models deepseg_gm_models deepseg_lesion_models c2c3_disc_models; do
    run sct_download_data -d "$data"
  done
fi

# Install deep learning models
python -c 'import spinalcordtoolbox.deepseg.models; spinalcordtoolbox.deepseg.models.install_default_models()'


# ----------------------------------------------------------------------------------------------------------------------
# Validate installation
# ----------------------------------------------------------------------------------------------------------------------

# conda is only for a sandbox; users don't use it,
# so neither should our post-install tests
conda deactivate >/dev/null 2>&1

# In case of previous SCT installation (4.0.0-beta.1 or before), remove sct_env declaration in bashrc
if [[ -e "$RC_FILE_PATH" ]]; then
    if grep "sct_env" "$RC_FILE_PATH"; then
      print info "In case an old version SCT is already installed (4.0.0-beta.1 or before), remove 'sct_env' declaration in RC file"
      perl -pi -e '/sct_env/ s/^#*/#/' "$RC_FILE_PATH"
    fi
    if grep "^export MPLBACKEND=Agg" "$RC_FILE_PATH"; then
      print info "Commenting out 'export MPLBACKEND=Agg' from previous SCT installation"
      perl -pi -e 's/^export MPLBACKEND=Agg/# The line below has been commented out by a more recent installation of SCT,\
# because export MPLBACKEND=Agg is no longer needed as of SCT v5.4.0\
# export MPLBACKEND=Agg/' "$RC_FILE_PATH"
    fi
fi

if [[ "$add_to_path" =~ ^[Yy] ]]; then
  edit_shellrc
else
  print info "Not adding $SCT_DIR to \$PATH.
You can always add it later or call SCT functions with full path $SCT_DIR/$BIN_DIR/sct_xxx"
fi

if [[ -n "$NO_INSTALL_VALIDATION" ]]; then
    print warning "WARNING: no checks will be run (installation will not be validated)"
else
  # run sct_check_dependencies
  print info "Validate installation..."
  # We run the sct_check_dependencies in the TMP_DIR so the tmp.XXX output
  # it creates is cleaned properly
  if sct_check_dependencies; then
    if [[ "$add_to_path" =~ ^[Nn] ]]; then
      print info "To use SCT, please update your environment by running:
  $DISPLAY_UPDATE_PATH"
    else
      print info "Open a new Terminal window to load environment variables, or run:
  source $RC_FILE_PATH"
    fi
  else
    die "Installation validation Failed!"
  fi
fi

) 2>&1 | tee install_sct_log.txt
status=${PIPESTATUS[0]}
popd >/dev/null
exit "$status"
