#!/bin/bash
# Script must be running from root
if [ "$EUID" -ne 0 ];
  then echo "Please run as root";
  exit 1;
fi;

this_repo_ipfs_cid="bafybeiepown476yzjs2zcymrn3t7d4oseuaw6a2rjnkdbu73jrp3evfdxm";
user_home_dir=$(eval echo ~$USER);
tornado_folder="$user_home_dir/tornado-ipfs";
script_log_file="/tmp/tornado-ipfs-installation.log";
cron_script_path="$tornado_folder/cronfile.cron";

function echo_log_err(){
  echo $1 1>&2;
  echo -e "$1\n" &>> $script_log_file;
}

function echo_log_err_and_exit(){
  echo_log_err "$1";
  exit 1;
}

function delete_if_exists(){
  if test -d $1; then rm -rf $1; fi;
  if test -f $1; then rm $1; fi;
}

function is_package_installed(){
  if [ $(dpkg-query -W -f='${Status}' $1 2>/dev/null | grep -c "ok installed") -eq 0 ]; then return 1; else return 0; fi;
}

function install_requred_packages(){
  apt update &>> $script_log_file;

  requred_packages=("curl" "git" "ufw" "cron");
  local package;
  for package in ${requred_packages[@]}; do
    if ! is_package_installed $package; then
      # Kill apache process, because Debian configuring nginx package  right during installation
      if [ $package = "nginx" ]; then systemctl stop apache2; fi; 
      echo "Start $package package installation";
      apt install --yes --force-yes  -o DPkg::Options::="--force-confold" $package &>> $script_log_file;
      if ! is_package_installed $package; then
        echo_log_err_and_exit "Error: cannot install \"$package\" package";
      fi;
    fi;
  done;

  echo -e "\nAll required packages installed successfully";
}

function install_node(){
  if ! command -v "nvm" &> $script_log_file; then
    curl -s -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.3/install.sh | bash &>> $script_log_file;
    . ~/.nvm/nvm.sh;
    . ~/.profile;
    . ~/.bashrc;
  fi;

  local required_node_version=16.20.2;
  nvm install $required_node_version &>> $script_log_file;
  nvm use $required_node_version &>> $script_log_file;
  echo $(node -v);
  if node -v | grep -q $required_node_version; then
    echo "Node $required_node_version successfully installed";
  else
    echo_log_err_and_exit "Cannot install node $required_node_version or node installed with error";
  fi;
}

function download_repo(){
  ipfs_gateways=("https://ipfs.io/ipfs" "https://dweb.link/ipfs" "https://cloudflare-ipfs.com/ipfs" "https://gateway.pinata.cloud/ipfs" "https://hardbin.com/ipfs");
  for gateway in ${ipfs_gateways[@]}; do
    delete_if_exists $tornado_folder;
    if git clone $gateway/$this_repo_ipfs_cid $tornado_folder; then break; fi;
  done;
  if [ ! -d $tornado_folder ]; then echo_log_err_and_exit "Cannot download repository from IPFS"; fi;
}

function install_node_dependencies(){
  npm i -g yarn &>> $script_log_file;
  cd $tornado_folder;
  yarn &>> $script_log_file;
}

function run_ipfs_daemon(){
  if ! command -v "ipfs" &> $script_log_file; then
    cd $tornado_folder;
    wget https://dist.ipfs.tech/kubo/v0.22.0/kubo_v0.22.0_linux-amd64.tar.gz &>> $script_log_file;
    tar -xvzf kubo_v0.22.0_linux-amd64.tar.gz;
    cd kubo;
    sudo bash install.sh &>> $script_log_file;
    ipfs init --profile server;
  fi;
  if ! ps aux | grep -w "ipfs daemon" | grep -v "grep"; then
    sudo -b ipfs daemon;
  fi;
}

function configure_firewall(){
  ufw allow OpenSSH;
  echo "y" | ufw enable;

  if ufw status | grep -qw active; then
    ufw allow 8080;
    ufw allow 4001;
    ufw deny 5000;
    ufw deny 5001;
    ufw reload;
    if ufw status | grep -qw 4001; then 
      echo "Peering ports for IPFS opened successfully via UFW";
    else
      echo_log_err $(ufw status);
      echo_log_err_and_exit "Cannot open ports for IPFS daemon, configure ufw please";
    fi;
  else 
    echo "UFW is disabled, ports already opened successfully, but need to close port 5001";
  fi;
}

function add_to_cron(){
  delete_if_exists $cron_script_path;

  # Add startup script to cron (job sheduler) to up IPFS daemon after restart
  echo "@reboot ipfs daemon &" > $cron_script_path;

  # Add existing cron rules (not related to this ipfs) to cron script, so that they are not removed
  # https://unix.stackexchange.com/questions/21297/how-do-i-add-an-entry-to-my-crontab
  crontab -l | grep -v "ipfs daemon" >> $cron_script_path;

  crontab $cron_script_path;
  systemctl restart cron;

  if crontab -l | grep -q "ipfs daemon"; then 
    echo "IPFS daemon added to cron autorun successfully";
  else
    echo_log_err "Warning: adding script to cron autorun failed.";
  fi;
}

function prepare_env(){
  cd $tornado_folder;
  delete_if_exists .env;
  local rpc_url="https://eth.llamarpc.com";
  echo "RPC_URL=$rpc_url" > .env;
  echo "ENS_ROOT_DOMAIN=tornadocash.eth" >> .env;
}

function run_pinner(){
  cd $tornado_folder;
  yarn pin;
}


install_requred_packages;
install_node;
download_repo;
install_node_dependencies;
run_ipfs_daemon;
configure_firewall;
add_to_cron;
prepare_env;
run_pinner;