#!/bin/bash

set -e

function showHelp() {
  cat << HELP
  🧙 arkanum ✨🌌☄️💥 is used to install optional runtimes for developing in a
  code-server container environment.

  Syntax: arkanum RUNTIME ...
  RUNTIME         [dotnet|golang|nodejs|powershell]
    dotnet               Installs latest LTS dotnet core sdk + runtime.
    gitea                Installs gitea tools like the changelog generator.
    golang               Installs golang 1.19.3.
    nodejs               Installs latest NodeJs LTS version using Volta.
    volta                Installs Volta as NodeJS version manager.
    powershell           Installs latest PowerShell LTS version.
  --disable-motd         Disables hint in new bash terminal.
  --install-extensions   Installs predefined recommended extensions.
  --reset-codesetting    Sets VS Code user setting with basic (Fira Code).
  -h                     Prints this help message.

  Example 1: arkanum dotnet
  Example 2: arkanum golang nodejs
  Example 3: arkanum --disable-motd
HELP
}

function disableMotd() {
  if [[ -e "$HOME/enable_motd" ]]; then
    say "Disabling 'arkanum' motd..." "disableMotd"
    rm -f "$HOME/enable_motd"
  fi
}

function say() {
  if [[ -n "$2" ]]; then
    echo -e "🧙 \e[32markanum\e[0m \e[34m[⚒️ $2]\e[0m: $1"
  else
    echo -e "🧙 \e[32markanum\e[0m: $1"
  fi
}

function sayE() {
  if [[ -n "$2" ]]; then
    echo -e "🧙 \e[31markanum\e[0m \e[34m[⚒️ $2]\e[0m: $1" 1>&2
  else
    echo -e "🧙 \e[31markanum\e[0m: $1" 1>&2
  fi
}

function sayW() {
  if [[ -n "$2" ]]; then
    echo -e "🧙 \e[33markanum\e[0m \e[34m[⚒️ $2]\e[0m: $1" 1>&2
  else
    echo -e "🧙 \e[33markanum\e[0m: $1" 1>&2
  fi
}

function instDotNet() {
  say "Installing dotnet requirements..." "dotnet"
  sudo -E apt-get update > /dev/null
  sudo -E apt-get install --no-install-recommends -y \
    libicu70

  say "Downloading latest install script..." "dotnet"
  curl -#fSL https://dot.net/v1/dotnet-install.sh -o /tmp/dotnet-install.sh
  chmod +x /tmp/dotnet-install.sh

  say "Installing latest .NET Core LTS release..." "dotnet"
  /tmp/dotnet-install.sh --channel LTS
  echo 'export PATH=$PATH:/config/.dotnet' | sudo tee -a /etc/bash.bashrc > /dev/null

  say "Cleaning up..." "dotnet"
  sudo -E apt-get clean
  sudo rm -rf \
    /tmp/* \
    /var/lib/apt/lists/* \
    /var/tmp/*
  say "dotnet done. " "dotnet"
}

function instGoLang() {
  if [[ -z "$1" ]]; then
    GOVERSION="1.20.6"
  else
    GOVERSION="$1"
  fi

  say "Downloading golang ($GOVERSION)..." "GoLang"
  curl -#fSL "https://go.dev/dl/go$GOVERSION.linux-amd64.tar.gz" -o /tmp/golang.tar.gz
  say "Installing golang ($GOVERSION)...." "GoLang"
  sudo rm -rf /usr/local/go
  sudo tar -C /usr/local -xzf /tmp/golang.tar.gz
  echo 'export PATH=$PATH:/usr/local/go/bin' | sudo tee -a /etc/bash.bashrc > /dev/null
  say "Cleaning up..." "GoLang"
  rm -f /tmp/golang.tar.gz
  say "done." "GoLang"
  say "Please reload bash profile to finalize." "GoLang"
}

function instNodeJs() {
  say "Adding nodesource package source (NodeJS LTS)..." "NodeJs"
  curl -#fSL https://deb.nodesource.com/setup_lts.x | sudo -E bash -
  say "Updating package lists and installing NodeJS LTS..." "NodeJs"
  sudo -E apt-get install --no-install-recommends -y \
    nodejs

  say "Cleaning up..." "NodeJs"
  sudo -E apt-get clean
  sudo rm -rf \
    /tmp/* \
    /var/lib/apt/lists/* \
    /var/tmp/*

  say "done." "NodeJs"
}

function instNodeJS2() {
  say "Installing NodeJS LTS via Volta..." "NodeJS"
  volta install node@lts
  say "done." "NodeJS"
}

function instVolta() {
  say "Installing Volta as NodeJS version manager..." "Volta"
  curl -#fSl https://get.volta.sh | bash
  say "done." "Volta"
}

function instPwsh() {
  say "Installing PowerShell requirements..." "PowerShell"
  sudo -E apt-get install --no-install-recommends -y \
    apt-transport-https \
    software-properties-common

  say "Adding powershell package sources..." "PowerShell"
  # Download the Microsoft repository GPG keys
  curl -#fSL "https://packages.microsoft.com/config/ubuntu/$(lsb_release -rs)/packages-microsoft-prod.deb" -o /tmp/packages-microsoft-prod.deb
  # Register the Microsoft repository GPG keys
  sudo dpkg -i /tmp/packages-microsoft-prod.deb
  # Update the list of packages after we added packages.microsoft.com
  sudo -E apt-get update

  say "Installing PowerShell..." "PowerShell"
  # Install PowerShell
  sudo -E apt-get install --no-install-recommends -y powershell

  say "done." "PowerShell"
}

function instGiteaTools() {
  TEA_VERSION="0.9.0"
  CHANGELOG_VERSION="main"
  say "Installing Gitea tools..." "Gitea"

  say "Downloading 'changelog' ($CHANGELOG_VERSION)..." "Gitea"
  sudo -E curl -#fSL "https://dl.gitea.io/changelog-tool/$CHANGELOG_VERSION/changelog-$CHANGELOG_VERSION-linux-amd64" -o /usr/bin/changelog
  sudo chmod +x /usr/bin/changelog
  say "'changelog' command installed." "Gitea"

  say "Downloading 'tea' ($TEA_VERSION)..." "Gitea"
  sudo -E curl -#fSL https://dl.gitea.io/tea/$TEA_VERSION/tea-$TEA_VERSION-linux-amd64 -o /usr/bin/tea
  sudo chmod +x /usr/bin/tea
  say "'tea' command installed." "Gitea"

  say "done." "Gitea"
}

function instCodeExtension() {
  say "Downloading required extensions...." "Extension"
  # Gitlens
  say "Downloading 'gitlens'..." "Extension"
  curl -#fSL https://open-vsx.org/api/eamodio/gitlens/13.1.1/file/eamodio.gitlens-13.1.1.vsix -o /tmp/eamodio.gitlens-13.1.1.vsix
  say "Installing 'gitlens'..." "Extension"
  install-extension /tmp/eamodio.gitlens-13.1.1.vsix
  say "Cleaning up 'gitlens' install files" "Extension"
  rm -f /tmp/eamodio.gitlens-13.1.1.vsix

  # OneDarkPro
  say "Downloading 'One Dark Pro' theme..." "Extension"
  curl -#fSL https://open-vsx.org/api/zhuangtongfa/material-theme/3.15.6/file/zhuangtongfa.material-theme-3.15.6.vsix -o /tmp/zhuangtongfa.material-theme-3.15.6.vsix
  say "Installing 'One Dark Pro' theme..." "Extension"
  install-extension /tmp/zhuangtongfa.material-theme-3.15.6.vsix
  say "Cleaning up 'One Dark Pro' install files" "Extension"
  rm -f /tmp/zhuangtongfa.material-theme-3.15.6.vsix

  # vscode-icons
  say "Downloading 'vscode-icons' theme..." "Extension"
  curl -#fSL https://open-vsx.org/api/vscode-icons-team/vscode-icons/12.0.1/file/vscode-icons-team.vscode-icons-12.0.1.vsix -o /tmp/vscode-icons-team.vscode-icons-12.0.1.vsix
  say "Installing 'vscode-icons' theme..." "Extension"
  install-extension /tmp/vscode-icons-team.vscode-icons-12.0.1.vsix
  say "Cleaning up 'vscode-icons' install files" "Extension"
  rm -f /tmp/vscode-icons-team.vscode-icons-12.0.1.vsix

  say "done." "Extension"
}
function setCodeSettings() {
  CODEFILE="$HOME/data/User/settings.json"

  # VSCode user settings file
  say "Setting VScode base settings.($CODEFILE)" "VSCode"
  cat <<EOF | tee "$CODEFILE"
{
  "window.menuBarVisibility": "compact",
  "workbench.colorTheme": "One Dark Pro Darker",
  "workbench.iconTheme": "vscode-icons",
  "editor.fontFamily": "'FiraCode', 'FiraCode Nerd Font', 'FiraCode NF', Consolas, 'Courier New', monospace",
  "terminal.integrated.fontFamily": "'FiraCode Mono', 'FiraCode Nerd Font Mono', 'FiraCode NFM', Consolas, monospace",
  "editor.fontLigatures": true,
  "editor.formatOnSave": true,
  "extensions.autoUpdate": false,
  "git.confirmSync": false,
  "telemetry.telemetryLevel": "off"
}
EOF
  say "done." "VSCode"
}

function main() {
  if [[ "$#" == "0" ]]; then
    showHelp
    exit 0
  fi

  for i in $@; do
    if [[ "$1" == "-h" ]]; then
      showHelp
      exit 0
    elif [[ "$i" == "dotnet" ]]; then
      instDotNet
    elif [[ "$i" == "golang" ]]; then
      instGoLang
    elif [[ "$i" == "nodejs" ]]; then
      if [[ "$2" == "--legacy" ]]; then
        sayW "Installing NodeJS with legacy function" "Arkanum"
        instNodeJs
      else
        instVolta
        instNodeJS2
      fi
    elif [[ "$i" == "volta" ]]; then
      instVolta
    elif [[ "$i" == "powershell" ]]; then
      instPwsh
    elif [[ "$i" == "gitea" ]]; then
      instGiteaTools
    elif [[ "$i" == "--disable-motd" ]]; then
      disableMotd
      exit 0
    elif [[ "$i" == "--install-extensions" ]]; then
      instCodeExtension
      exit 0
    elif [[ "$i" == "--reset-codesetting" ]]; then
      setCodeSettings
      exit 0
    else
      sayE "Unknown parameter value given!($i)."
      showHelp
      exit 1
    fi
  done
}

main $@
