#!/bin/bash

# This setups a Python venv, installs some packages,
# setups some start files, and adds VSCode extenstions.
# As is, it is suitable to use on the VM infrastructure used in e.g.
# BC07-08 or CO02x. It will probably not work right away on local VM
# images may lack automatic mounting of myfiles at ~/Desktop/myfiles.
# Authors: Jean-Philippe Pellet, Matthieu Bovel
# Version: 2024-02-14

SEMESTER="2024Fall"
PYTHON_EXEC=python3.12
PYTHON_VERSION="3.12.2"
PYTHON_PATH="/opt/python3.12.2/bin/${PYTHON_EXEC}" 
COURSEFOLDERNAME="ENG209_${SEMESTER}"

echostep() {
    str="$1"
    len=${#str}
    pad="$(printf %-$((len + 5))s '')"
    pre="$(tput bold)$(tput setaf 4)$(tput rev)"
    post="$(tput sgr0)"
    echo ""
    echo "----"
    echo "$pre$pad$post"
    echo "$pre>> $1  $post"
    echo "$pre$pad$post"
    echo "----"
}

clear

echostep "Creating a ${PYTHON_EXEC} virtual environment on myfiles..."

cd ~/Desktop/myfiles
mkdir -p "$COURSEFOLDERNAME"
cd "$COURSEFOLDERNAME"
mkdir -p venv/lib64 # needed to avoid symlink creation error on smb share
"$PYTHON_PATH" -m venv --copies venv
source venv/bin/activate

echostep "Installing Python packages..."

pip install --upgrade pip
pip install ipykernel
pip install matplotlib
pip install numpy
pip install pandas
pip install func_timeout # for testing harness
pip install bpython # interpreter with completion and syntax highlighting
pip install mypy


echostep "Finishing setup in myfiles..."

mkdir -p .vscode

# This can be of course tweaked to reflect the best initial options for
# the created VS Code workspace. Careful with $, which must be escaped.
rm -f *.code-workspace
cat > .vscode/settings.json << EOM
// Ce fichier détermine les paramètres de votre workspace.
// Merci de ne pas le modifier à moins que la donnée d'un
// exercice vous demande de le faire.
{
    "workbench.editor.showTabs": "multiple",
    "workbench.tree.indent": 20,
    "python.envFile": "\${workspaceFolder}/venv",
    "python.defaultInterpreterPath": "venv/bin/python",
    "python.terminal.activateEnvironment": true,
    "python.terminal.activateEnvInCurrentTerminal": true,
    "[python]": {
        "editor.formatOnSave": true,
        "editor.defaultFormatter": "ms-python.black-formatter"
    },
    "mypy.checkNotebooks": true,
    "mypy.mypyExecutable": "\${workspaceFolder}/venv/bin/mypy",
    "mypy.dmypyExecutable": "\${workspaceFolder}/venv/bin/dmypy",
    "files.watcherExclude": {
        "**/.env/**": true,
        "**/venv/**": true,
        "**/.mypy_cache": true,
        "**/.ipynb_checkpoints": true
    },
    "files.exclude": {
        "**/.env/**": true,
        "**/venv/**": true,
        "**/.mypy_cache": true,
        "**/.ipynb_checkpoints": true
    },
    "python.terminal.activateEnvInCurrentTerminal": false
}
EOM

# Allows silencing some of the mypy warnings.
rm -f mypy.ini
cat > mypy.ini << EOM
[mypy]

[mypy-numpy]
ignore_missing_imports = True
EOM

# Predefined tasks can be provided like this
rm -f .vscode/tasks.json
cat > .vscode/tasks.json << EOM
{
    "version": "2.0.0",
    "tasks": [
        {
            "label": "bpython",
            "type": "shell",
            "command": "source venv/bin/activate && venv/bin/bpython",
            "problemMatcher": [],
            "presentation": {
                "focus": true,
                "showReuseMessage": true,
                "echo": false,
                "panel": "dedicated"
            }
        }
    ]
}
EOM



# Simple Python test file. It shows the version number,
# and has a type error that should be highlighted in red, checking
# that the type checker is active. Correcting and saving then
# should (according to workspace settings) autoformat the file
# and add spaces around '='
if [ ! -f test.py ]; then
	cat > test.py << EOM
# Cliquez sur le bouton Play en haut à droite pour exécuter ceci.

import sys

version = sys.version_info
msg: str = f"Welcome to Python {version.major}.{version.minor}.{version.micro}!"
print(msg)

# Ceci devrait être souligné en rouge car il y a une erreur de type,
# sans toutefois empêcher l'exécution du code. Rajoutez des guillemets
# autour de 3 pour corriger l'erreur. Normalement, le formatage automatique
# du code lors de la sauvegarde du fichier devrait ensuite automatiquement
# insérer des espaces autour du symbole =.
msg=3
EOM
fi

# Simple notebook test file
if [ ! -f test.ipynb ]; then
	cat > test.ipynb << EOM
{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Bienvenue sur les Jupyter Notebooks!\n",
    "\n",
    "Ceci est un moyen, sur une même «page», de proposer du contenu textuel et des extraits de code, qui peuvent être exécutés et qui sont potentiellement modifiables.\n",
    "\n",
    "Chacune des cellules de type «code» ci-dessous peut être évaluée en cliquant dessus puis en tapant Majuscule-Retour."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "6"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "3 + 3"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "9"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "3 * 3"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Supprimez la première ligne de la cellule suivante pour supprimer l'erreur de type:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "27"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = \"3\"\n",
    "a = 3\n",
    "a ** a"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
EOM
fi

# Key bindings are directly put in the user's settings folder,
# they can't be loaded from workspace settings
cd ~/Desktop/myfiles
mkdir -p epfl_roaming/ic_in-sc/.Code/User/
rm -f epfl_roaming/ic_in-sc/.Code/User/keybindings.json
cat > epfl_roaming/ic_in-sc/.Code/User/keybindings.json << EOM
// Custom keybindings for the course
[
    {
        "key": "ctrl+j",
        "command": "-workbench.action.togglePanel"
    },
    {
        "key": "ctrl+i",
        "command": "workbench.action.tasks.runTask",
        "args": "bpython"
    },
    {
        "key": "ctrl+j",
        "command": "workbench.action.tasks.runTask",
        "args": "jupyter"
    }
]
EOM


echostep "Installing VS Code extensions..."

code --install-extension ms-python.python --force
code --install-extension ms-python.black-formatter --force
code --install-extension ms-python.mypy-type-checker --force
code --install-extension matangover.mypy --force # because it can check notebooks
code --install-extension jock.svg --force
code --uninstall-extension formulahendry.code-runner 2> /dev/null || echo "Legacy code-runner not installed, good"

echostep "Done. Launching VS Code and opening folder '${COURSEFOLDERNAME}'..."

code ~/Desktop/myfiles/"${COURSEFOLDERNAME}"
