#!/bin/sh
# A helper script to install Eggdrop
# Written by Geo, Lord255, 2024


# variables
# --------------------
script_version="v0.9.9"

# colors
reset="\e[0m"
green="\e[0;32m"
red="\e[0;31m"
tan='\e[0;33m'
blue='\e[38;5;74m'

installpath=""
timestamp=""

# not used atm
#ostype=`grep '^ID\=' /etc/os-release | cut -d "=" -f2 | tr -d \"\"`


# functions
# --------------------
log() {
  printf "%b" "${reset}${blue}::: ${1}${reset}\n"
}

goodlog() {
  printf "%b" "${reset}${green}::: ${1}${reset}\n"
}

warn() {
  printf "%b" "${reset}${tan}::: ${1}${reset}\n"
}

error() {
  printf "%b" "${reset}${red}*** ${1}${reset}\n"
}

bigerror() {
  printf "%b" "${reset}${red}-----------------------------------------------------------------${reset}\n"
  printf "%b" "${reset}${red}*** ERROR - ${1}${reset}\n"
  exit
}

question() {
  printf "%b" "${reset}${blue}::: ${1}${reset}"
}

newline() {
   printf "%b" "\n"
}

splash() {
printf "%b" "${blue}"
cat << "EOF"

Thank you for choosing
    ______                __               
   / ____/___ _____ _____/ /________  ____ 
  / __/ / __ `/ __ `/ __  / ___/ __ \/ __ \
 / /___/ /_/ / /_/ / /_/ / /  / /_/ / /_/ /
/_____/\__, /\__, /\__,_/_/   \____/ .___/ 
      /____//____/                /_/      
===========================================
EOF
printf "%b" "${reset}"
log "Script version ${script_version}"
newline
}

getInput() {
  yn=${1}
  while true; do
    if [ -z "${yn}" ]; then
      yn="y"
    fi
    case ${yn} in
      [Yy]*)
        yn="y"
        break;;
      [Nn]*)
        yn="n"
# Do we still need this line?
#        printf "%b" "\e[0m"
        break;;
      *)
        log "Please answer yes or no.";
        question "Choice [Y/n]: "
        read -rp "" yn
      ;;
    esac
  done
}

downloadSource() {
  if [ ! "$(which tar)" ]; then
    error "You do not appear to have tar installed on this system. Please"
    error "install it and try again."
    error "Exiting."  
    exit
  fi
  if [ ! "$(which sudo)" ]; then
    error "You do not appear to have sudo installed on this system. Please"
    error "install it and try again."
    error "Exiting."
  fi
  dlUrl="https://geteggdrop.com"
  if [ "$(which curl)" ]; then
    dlTool="curl --connect-timeout 5 -L $dlUrl --output eggdrop-src.tar.gz"
  else
    if [ "$(which wget)" ]; then
      dlTool="wget -T 5 -O eggdrop-src.tar.gz $dlUrl"
    else
      error "You do not have either the curl or wget download tools installed"
      error "on this system. Please install one and try again."
      exit
    fi
  fi
  log "Downloading Eggdrop..."
  ${dlTool}
  log "Extracting Eggdrop..."
  tar zxf eggdrop-src.tar.gz
  newesteggfolder=$(ls -dt1 eggdrop-*/ | head -n1 | cut -d "/" -f1)
  eggsourcepath="${PWD}/${newesteggfolder}"
  cd "${eggsourcepath}" || bigerror
}

checkInit() {
  if [ $(id -u) = 0 ] ; then
    error "This installer cannot be run as root. Please log in as the user you"
    error "wish to run Eggdrop from and re-run this installer."
    error "Exiting."
    exit
  fi

  if [ ! -f "${PWD}/src/version.h" ]; then
    log "You do not appear to be running this script from inside a directory"
    log "containing Eggdrop source code."
    question "Would you like to download Eggdrop? [Y/n]: "
    read -rp "" yn
    getInput "${yn}"
    if [ "${yn}" = "n" ]; then
      exit
    fi
    downloadSource
  else
    eggsourcepath="${PWD}"
  fi
}

introMessage() {
  log "This script will walk you through the installation process for Eggdrop."
  log "If you have a specific install requirement that falls outside of a default"
  log "one-click solution, please abort this script and consult README and INSTALL."
  newline
  question "Do you wish to install Eggdrop? [Y/n]: "
  read -rp "" yn
  getInput "${yn}"
    if [ "${yn}" = "n" ]; then
      exit
    fi
}

checkOS() {
  log "Checking for package manager..."
  PKG=""
  while true; do
    if PKG="$(which apt-get 2>/dev/null)"; then
      zpkg="apt-get"
      break
    fi
    if PKG="$(which yum 2>/dev/null)"; then
      zpkg="yum"
      break
    fi
    if PKG="$(which dnf 2>/dev/null)"; then
      zpkg="dnf"
      break
    fi
    if PKG="$(which pacman 2>/dev/null)"; then
      zpkg="pacman"
      break
    fi
    if PKG="$(which emerge 2>/dev/null)"; then
      zpkg="emerge"
      break
    fi
    if PKG="$(which zypper 2>/dev/null)"; then
      zpkg="zypper"
      break
    fi
    break
  done
  if [ -z "${PKG}" ]; then
    error "No suitable package manager found."
    error "Exiting."
    exit
  else
    goodlog " - Found: ${PKG}"
  fi
}

checkDependencies() {
  i=0
  missing=""
  log "Checking dependencies..."  
  if [ ${zpkg} = "apt-get" ]; then
    pkgs="gcc make tcl tcl-dev openssl libssl-dev"
    for pkg in ${pkgs}; do
      srcCmd="dpkg -s ${pkg}"
      ${srcCmd} > /dev/null 2>&1
      if [ $? -eq 1 ]; then
        warn "  - ${pkg} not found."
        missing="${missing} ${pkg}"
        i=$((i+1))
      fi
    done
  fi

  if [ ${zpkg} = "yum" ]; then
    pkgs="gcc make tcl tcl-devel openssl openssl-devel"
    for pkg in ${pkgs}; do
      srcCmd="${zpkg} list installed ${pkg}"
      ${srcCmd} > /dev/null 2>&1
      if [ $? -eq 1 ]; then
        warn "  - ${pkg} not found."
        missing="${missing} ${pkg}"
        i=$((i+1))
      fi
    done
  fi

  if [ ${zpkg} = "dnf" ]; then
    pkgs="gcc make tcl tcl-devel openssl openssl-devel"
    for pkg in ${pkgs}; do
      srcCmd="${zpkg} list installed ${pkg}"
      ${srcCmd} > /dev/null 2>&1
      if [ $? -eq 1 ]; then
        warn "  - ${pkg} not found."
        missing="${missing} ${pkg}"
        i=$((i+1))
      fi
    done
  fi

  if [ ${zpkg} = "emerge" ]; then
    pkgs="dev-lang/tcl dev-libs/openssl"
    for pkg in ${pkgs}; do
      srcCmd="qlist -I ${pkg}"
      ${srcCmd} > /dev/null 2>&1
      if [ $? -eq 1 ]; then
        warn "  - ${pkg} not found."
        missing="${missing} ${pkg}"
        i=$((i+1))
      fi
    done
  fi

  if [ ${zpkg} = "pacman" ]; then
    pkgs="gcc make tcl openssl"
    for pkg in ${pkgs}; do
      srcCmd="pacman -Qi ${pkg}"
      ${srcCmd} > /dev/null 2>&1
      if [ $? -eq 1 ]; then
        warn "  - ${pkg} not found."
        missing="${missing} ${pkg}"
        i=$((i+1))
      fi
    done
  fi

  if [ ${zpkg} = "zypper" ]; then
    pkgs="gcc make tcl tcl-devel openssl openssl-devel"
    for pkg in ${pkgs}; do
      srcCmd="rpm -q ${pkg}"
      ${srcCmd} > /dev/null 2>&1
      if [ $? -eq 1 ]; then
        warn "  - ${pkg} not found."
        missing="${missing} ${pkg}"
        i=$((i+1))
      fi
    done
  fi

  if [ -n "${missing}" ]; then
    error "Missing packages: ${missing}"
    log "Software libraries were detected as missing on this system."
    question "Would you like to install them? (will require sudo permission) [Y/n]: "
    read -rp "" yn
    getInput "${yn}"
    if [ "${yn}" = "n" ]; then
      exit
    fi
    installDependencies
  else
    goodlog "All necessary packages are installed."
  fi
}

installDependencies() {
  log "Using ${zpkg}...."
  if [ ${zpkg} = "apt-get" ]; then
    sudo apt-get update && sudo apt-get install "${missing}" -y
  fi

  if [ ${zpkg} = "yum" ]; then
    sudo ${zpkg} update && sudo ${zpkg} install "${missing}" -y
  fi
  
  if [ ${zpkg} = "dnf" ]; then
    sudo ${zpkg} update && sudo ${zpkg} install "${missing}"
  fi

  if [ ${zpkg} = "emerge" ]; then
    sudo emerge --sync && sudo emerge -av "${missing}"
  fi

  if [ ${zpkg} = "pacman" ]; then
    sudo pacman -Sy "${missing}"
  fi

  if [ ${zpkg} = "zypper" ]; then
    sudo zypper install "${missing}"
  fi

  checkDependencies
}

startCompile() {
  log "Starting compile process..."
  cd "${eggsourcepath}" || bigerror
  if [ ! -f configure ]; then
    bigerror "Compile process aborted. 'configure' file not found. (Are you in the right folder?)"
    exit
  else
    ./configure || bigerror "Configure aborted. See log above."
  fi
  log "Now running make config..."
  make config || bigerror "Make aborted. See log above."
  log "Now running make ..."
  make || "Make config aborted. See log above."
  question "Where would you like to install Eggdrop? [~/eggdrop]: "
  read -rp "" installpath
  # Expand install path (~) if needed
  installpath=$(eval echo "${installpath}")
  if [ -z "${installpath}" ]; then
    installpath="$HOME/eggdrop"
  fi
  if [ -f "${installpath}"/eggdrop-basic.conf ]; then
    warn "Previous install of Eggdrop detected."
    question "Do you want to archive the existing version of eggdrop-basic.conf in ${installpath} and create a fresh config file? [Y/n]: "
    read -rp "" yn
    getInput "${yn}"
    if [ "${yn}" = "n" ]; then
      useoldconfig=1
      goodlog "Keeping existing eggdrop-basic.conf"
    else
      usenewconfig=1
      timestamp=$(date +%s)
      goodlog "Backing up existing eggdrop-basic.conf file to ${installpath}/eggdrop-basic.conf.${timestamp}.backup"
      mv "${installpath}"/eggdrop-basic.conf "${installpath}"/eggdrop-basic."${timestamp}".backup
    fi
  fi
  make install DEST="${installpath}" || bigerror "Installation failed, see log above for details"
  if [ -z "${useoldconfig}" ]; then
    log "Generating public/private keypair for secure TLS connections..."
    make sslcert DEST="${installpath}"
  fi
}

buildConfig_defaults() {
    sed -i "s|^#! /path/to/executable/eggdrop|#! ${installpath}/eggdrop|" "${installpath}"/eggdrop-basic.conf
    goodlog "Updated config shebang to ${installpath}/eggdrop-basic.conf"
    sed -i 's/^#set ssl-privatekey "eggdrop.key"/set ssl-privatekey "eggdrop.key"/' "${installpath}"/eggdrop-basic.conf
    sed -i 's/^#set ssl-certificate "eggdrop.crt"/set ssl-certificate "eggdrop.crt"/' "${installpath}"/eggdrop-basic.conf
    goodlog "Enabled SSL/TLS keys in ${installpath}/eggdrop-basic.conf"
}

buildConfig_botnick() {
    question "What nickname would you like to use for your Eggdrop? [LlamaBot]: "
    read -rp "" botnick
    if [ -z "${botnick}" ]; then
      botnick="LlamaBot"
    fi
    sed -i "/^set nick/s/.*/set nick \"${botnick}\"/" "${installpath}"/eggdrop-basic.conf
    goodlog "Nickname set to ${botnick}"
    log "This value can be changed later by editing the \"set nick\" variable in ${installpath}/eggdrop-basic.conf"
}

buildConfig_network_update() {
    lastserveradd=$(grep -n "^#server add" "${installpath}/eggdrop-basic.conf" | tail -n 1 | cut -d ":" -f1)
    sed -i "$((lastserveradd + 1))i server add ${1}" "${installpath}"/eggdrop-basic.conf
    goodlog "Added ${1} to ${installpath}/eggdrop-basic.conf"
    sed -i "/^set net-type/c\set net-type ${2}" "${installpath}"/eggdrop-basic.conf
    goodlog "Updated net-type to ${2}"
}

buildConfig_network_choice() {
    log "What IRC network would you like Eggdrop to join?"
    log "Available default servers:"
    log "--------------------------"
    log "1) Libera"
    log "2) Undernet"
    log "3) EFnet"
    log "4) DALnet"
    log "5) Other - modify eggdrop-basic.conf to add"
    question "Please make your choice: [1]: "
    read -rp "" network 

    # no network -> default network -> 1
    if [ -z "${network}" ]; then
        network=1
    fi
    while true; do
      if [ "${network}" -ge 1 ] && [ $network -le 5 ]; then
        break
      else
          warn "Invalid choice. Please enter a number between 1 and 5: "
          read -rp "" network
      fi
    done

    # Remove old servers
    sed -i 's/^server add/#server add/' "${installpath}"/eggdrop-basic.conf
    # Add selected server
    while true; do
      if [ "${network}" -eq 1 ]; then
        buildConfig_network_update "irc.libera.chat 6667" "Libera"
        break
      fi
      if [ "${network}" -eq 2 ]; then
        buildConfig_network_update "irc.undernet.org 6667" "Undernet"
        break
      fi
      if [ "${network}" -eq 3 ]; then
        buildConfig_network_update "irc.efnet.org 6667" "EFnet"
        break
      fi
      if [ "${network}" -eq 4 ]; then
        buildConfig_network_update "irc.dal.net" "6667"
        break
      fi
      if [ "${network}" -eq 5 ]; then
        log "Please edit ${installpath}/eggdrop-basic.conf and follow the examples to add the server you like via the 'server add <hostname> <port>' command"
        break
      fi
    done
}

buildConfig() {
  question "Would you like to configure the nickname and server for Eggdrop to use? [Y/n]: "
  read -rp "" yn
  getInput "${yn}"
  if [ "${yn}" = "n" ]; then
    return
  fi
  if [ ! -f "${installpath}/eggdrop-basic.conf" ]; then
    bigerror "Could not find ${installpath}/eggdrop-basic.conf for editing. Skipping..."
  else
    # set nickname
    buildConfig_botnick
    newline
    
    # select network and add server
    buildConfig_network_choice
    
    # set the defaults (shebang; crt/key file)
    buildConfig_defaults
    newline
    
    log "Additional servers can be added using the \"add server\" command in ${installpath}/eggdrop-basic.conf"
    newline
  fi 
  if [ -z ${usenewconfig} ]; then
    log "The previous eggdrop-basic.conf was backed up to ${path}/eggdrop-basic.conf.${timestamp}.backup"
    newline
  fi
  log "These are only a few of hundreds of settings available for configuration on Eggdrop."
  log "We HIGHLY recommend you to check/edit the ${installpath}/eggdrop-basic.conf file,"
  log "to get an idea of the basic/core options available and then when you're ready,"
  log "read the full ${installpath}/eggdrop.conf file."
  log "Enjoy!"
  newline
}


# core
# --------------------
splash
checkInit
newline

introMessage
newline

checkOS
checkDependencies
newline

startCompile
newline

if [ -z ${useoldconfig} ]; then
  buildConfig
fi

goodlog "Installation complete!"
newline
log "Please cd to ${installpath} and run './eggdrop -m eggdrop-basic.conf' to start your Eggdrop"
newline
