#!/bin/bash

# Dirs
SCRIPTS=/var/scripts
HTML=/var/www
NCPATH="$HTML"/nextcloud
POOLNAME=ncdata
NCDATA=/mnt/"$POOLNAME"
SNAPDIR=/var/snap/spreedme
GPGDIR=/tmp/gpg
SHA256_DIR=/tmp/sha256
BACKUP=/mnt/NCBACKUP
NC_APPS_PATH=$NCPATH/apps
VMLOGS=/var/log/nextcloud


DISTRO=$(lsb_release -sr)
CODENAME=$(lsb_release -sc)
KEYBOARD_LAYOUT=$(localectl status | grep "Layout" | awk '{print $3}')
# Hypervisor
###  TODO ### HYPERVISOR=$(dmesg --notime | grep -i hypervisor | cut -d ':' -f2 | head -1 | tr -d ' ')
SYSVENDOR=$(cat /sys/devices/virtual/dmi/id/sys_vendor)
# Network
IFACE=$(ip r | grep "default via" | awk '{print $5}')
IFACE2=$(ip -o link show | awk '{print $2,$9}' | grep 'UP' | cut -d ':' -f 1)
ADDRESS=$(hostname -I | cut -d ' ' -f 1)
WANIP4=$(curl -s -k -m 5 -4 https://api64.ipify.org)
INTERFACES="/etc/netplan/nextcloud.yaml"
GATEWAY=$(ip route | grep default | awk '{print $3}')

# Repo
GITHUB_REPO="https://raw.githubusercontent.com/nextcloud/vm/main"
STATIC="$GITHUB_REPO/static"
LETS_ENC="$GITHUB_REPO/lets-encrypt"
APP="$GITHUB_REPO/apps"
OLD="$GITHUB_REPO/old"
ADDONS="$GITHUB_REPO/addons"
DESEC="$GITHUB_REPO/addons/deSEC"
MENU="$GITHUB_REPO/menu"
DISK="$GITHUB_REPO/disk"
NETWORK="$GITHUB_REPO/network"
VAGRANT_DIR="$GITHUB_REPO/vagrant"
NOT_SUPPORTED_FOLDER="$GITHUB_REPO/not-supported"
NCREPO="https://download.nextcloud.com/server/releases"
ISSUES="https://github.com/nextcloud/vm/issues"


# User information
GUIUSER=ncadmin
GUIPASS=nextcloud
UNIXUSER=$SUDO_USER
UNIXUSER_PROFILE="/home/$UNIXUSER/.bash_profile"
ROOT_PROFILE="/root/.bash_profile"

# User for Bitwarden
BITWARDEN_USER=bitwarden
BITWARDEN_HOME=/home/"$BITWARDEN_USER"



# GeoBlock
GEOBLOCK_MOD_CONF="/etc/apache2/conf-available/geoblock.conf"
GEOBLOCK_MOD="/etc/apache2/mods-available/maxminddb.load"
GEOBLOCK_DIR="/usr/share/GeoIP"
# PHP-FPM
PHPVER=8.4
PHP_FPM_DIR=/etc/php/$PHPVER/fpm
PHP_INI=$PHP_FPM_DIR/php.ini
PHP_POOL_DIR=$PHP_FPM_DIR/pool.d
PHP_MODS_DIR=/etc/php/"$PHPVER"/mods-available
opcache_interned_strings_buffer_value=24
# Notify push
NOTIFY_PUSH_SERVICE_PATH="/etc/systemd/system/notify_push.service"

# NOTE config files
FSTAB="/etc/fstab"

# Install curl if not existing
if dpkg-query -W -f='${Status}' "curl" 2>/dev/null | grep -q "ok installed"
then
    echo "curl OK"
else
    apt-get update -q4
    apt-get install curl -y
fi

# Helper function for generating random passwords
gen_passwd() {
    local length=$1
    local charset="$2"
    local password=""
    while [ ${#password} -lt "$length" ]
    do
        password=$(echo "$password""$(head -c 100 /dev/urandom | LC_ALL=C tr -dc "$charset")" | fold -w "$length" | head -n 1)
    done
    echo "$password"
}

# Database
SHUF=$(shuf -i 25-29 -n 1)
PGDB_USER=nextcloud_db_user
PGDB_PASS=$(gen_passwd "$SHUF" "a-zA-Z0-9@#*")
NEWPGPASS=$(gen_passwd "$SHUF" "a-zA-Z0-9@#*")


is_root() {
    if [[ "$EUID" -ne 0 ]]
    then
        return 1
    else
        return 0
    fi
}

# Check if root
root_check() {
if ! is_root
then
    msg_box "Sorry, you are not root. You now have two options:

1. Use SUDO directly:
   a) :~$ sudo bash $SCRIPTS/name-of-script.sh

2. Become ROOT and then type your command:
   a) :~$ sudo -i
   b) :~# bash $SCRIPTS/name-of-script.sh

In both cases above you can leave out $SCRIPTS/ if the script
is directly in your PATH.

More information can be found here: https://unix.stackexchange.com/a/3064"
    exit 1
fi
}

debug_mode() {
if [ "$DEBUG" -eq 1 ]
then
    set -ex
fi
}


# Check if program is installed (stop_if_installed apache2)
stop_if_installed() {
if [ "$(dpkg-query -W -f='${Status}' "${1}" 2>/dev/null | grep -c "ok installed")" = "1" ]
then
    print_text_in_color "$IRed" "${1} is installed, it must be a clean server."
    exit 1
fi
}

# Check if program is installed (is_this_installed apache2)
is_this_installed() {
if dpkg-query -W -f='${Status}' "${1}" | grep -q "ok installed"
then
    return 0
else
    return 1
fi
}



# Install_if_not program
install_if_not() {
if ! dpkg-query -W -f='${Status}' "${1}" | grep -q "ok installed"
then
   sudo apt-get update -q4 && RUNLEVEL=1 sudo apt-get install "${1}" -y
fi
}



ncdb() {
    NCDB=$(grep "dbname" $NCPATH/config/config.php | awk '{print $3}' | sed "s/[',]//g")
    NCDBPASS=$(grep "dbpassword" $NCPATH/config/config.php | awk '{print $3}' | sed "s/[',]//g")
    NCDBUSER=$(grep "dbuser" $NCPATH/config/config.php | awk '{print $3}' | sed "s/[',]//g")
    NCDBTYPE=$(grep "dbtype" /var/www/nextcloud/config/config.php | awk '{print $3}' | sed "s/[',]//g")
    NCDBHOST=$(grep "dbhost" /var/www/nextcloud/config/config.php | awk '{print $3}' | sed "s/[',]//g")
}

# Talk
turn_install() {
    TURN_CONF="/etc/turnserver.conf"
    TURN_PORT=3478
    TURN_DOMAIN=$(sudo -u www-data /var/www/nextcloud/occ config:system:get overwrite.cli.url | sed 's|https://||;s|/||')
    SHUF=$(shuf -i 25-29 -n 1)
    TURN_SECRET=$(gen_passwd "$SHUF" "a-zA-Z0-9")
    JANUS_API_KEY=$(gen_passwd "$SHUF" "a-zA-Z0-9")
    SIGNALING_SECRET=$(gen_passwd "$SHUF" "a-zA-Z0-9")
    SIGNALING_SERVER_CONF=/etc/signaling/server.conf
    TURN_INTERNAL_SECRET=$(gen_passwd "$SHUF" "a-zA-Z0-9")
    TURN_RECORDING_SECRET=$(gen_passwd "$SHUF" "a-zA-Z0-9")
    TURN_RECORDING_HOST=127.0.0.1
    TURN_RECORDING_HOST_PORT=1234
}


# Used in geoblock.sh
download_geoip_mmdb() {
    # Rate limit to 1 hour, we have 24 requests per day
    if [ -f "$GEOBLOCK_DIR/IPInfo-Country.mmdb" ]
    then
        if [ "$(( $(date +"%s") - $(stat -c "%Y" "$GEOBLOCK_DIR/IPInfo-Country.mmdb") ))" -lt "3600" ]
        then
            print_text_in_color "$IGreen" "No need to update $GEOBLOCK_DIR/IPInfo-Country.mmdb since it's newer than 1 hour."
            return 1
        fi
    elif [ -f "$GEOBLOCK_DIR/GeoLite2-Country.mmdb" ]
    then
        print_text_in_color "$ICyan" "Replacing Maxmind with IPInfo GeoIP database..."
    fi

    # Download or update current GeoIP DB
    maxmind_geoip
    export x8v8GyVQg2UejdPh
    print_text_in_color "$ICyan" "Downloading latest GeoIP database from https://ipinfo.io..."
    if ! curl -sfL https://ipinfo.io/data/free/country.mmdb?token="$x8v8GyVQg2UejdPh" -o "$GEOBLOCK_DIR"/IPInfo-Country.mmdb
    then
        print_text_in_color "$IRed" "Failed downloading GeoIP database from IPInfo, trying plan B..."
        export MwKfcYATm43NMT
        export i9HL69SLnp4ymy
        {
        echo "GEOIPUPDATE_ACCOUNT_ID=$MwKfcYATm43NMT"
        echo "GEOIPUPDATE_LICENSE_KEY=$i9HL69SLnp4ymy"
        echo "GEOIPUPDATE_EDITION_IDS=GeoLite2-Country"
        echo "GEOIPUPDATE_FREQUENCY=0"
        echo "GEOIPUPDATE_PRESERVE_FILE_TIMES=1"
        echo "GEOIPUPDATE_VERBOSE=1"
        } > /tmp/dockerenv
        unset MwKfcYATm43NMT
        unset i9HL69SLnp4ymy
        install_docker
        if docker run --name maxmind --env-file /tmp/dockerenv -v "$GEOBLOCK_DIR":"$GEOBLOCK_DIR" ghcr.io/maxmind/geoipupdate
        then
            docker rm -f maxmind
            rm -f /tmp/dockerenv
            # Since only one mmdb file can exist at the same time due to Apache "if" confitions, remove IPInfos config
            rm -f "$GEOBLOCK_DIR"/IPInfo-Country.mmdb
            print_text_in_color "$IGreen" "Maxmind GeoIP database downloaded!"
        else
            docker rm -f maxmind
            rm -f /tmp/dockerenv
            print_text_in_color "$IRed" "Rate limit for Maxmind GeoIP database reached! Can't continue from here, please report this to $ISSUES"
        fi
    else
        # Since only one mmdb file can exist at the same time due to Apache "if" confitions, remove MaxMinds config
        rm -f "$GEOBLOCK_DIR"/GeoLite2-Country.mmdb
        return 0
    fi
    unset x8v8GyVQg2UejdPh
}

# $1=domain/ip-address
add_to_trusted_domains() {
    local element="$1"
    local count=0
    print_text_in_color "$ICyan" "Adding $element to trusted domains..."
    while [ "$count" -le 10 ]
    do
        if [ "$(nextcloud_occ_no_check config:system:get trusted_domains "$count")" = "$element" ]
        then
            break
        elif [ -z "$(nextcloud_occ_no_check config:system:get trusted_domains "$count")" ]
        then
            nextcloud_occ_no_check config:system:set trusted_domains "$count" --value="$element"
            break
        else
            count=$((count+1))
        fi
    done
}

# $1=domain/ip-address
remove_from_trusted_domains() {
    local element="$1"
    local count=0
    print_text_in_color "$ICyan" "Removing $element from trusted domains..."
    while [ "$count" -lt 10 ]
    do
        if [ "$(nextcloud_occ_no_check config:system:get trusted_domains "$count")" = "$element" ]
        then
            nextcloud_occ_no_check config:system:delete trusted_domains "$count"
            break
        else
            count=$((count+1))
        fi
    done
}


# Example: nextcloud_occ_no_check 'maintenance:mode --on'
nextcloud_occ() {
# Check it maintenance:mode is enabled
if sudo -u www-data php "$NCPATH"/occ maintenance:mode | grep -q enabled >/dev/null 2>&1
then
    # Disable maintenance:mode
    sudo -u www-data php "$NCPATH"/occ maintenance:mode --off >/dev/null 2>&1
    # Run the actual command
    check_command sudo -u www-data php "$NCPATH"/occ "$@";
    # Enable maintenance:mode again
    sudo -u www-data php "$NCPATH"/occ maintenance:mode --on >/dev/null 2>&1
else
    check_command sudo -u www-data php "$NCPATH"/occ "$@";
fi
}

# Example: nextcloud_occ_no_check 'maintenance:mode --on'
nextcloud_occ_no_check() {
# Check it maintenance:mode is enabled
if sudo -u www-data php "$NCPATH"/occ maintenance:mode | grep -q enabled >/dev/null 2>&1
then
    # Disable maintenance:mode
    sudo -u www-data php "$NCPATH"/occ maintenance:mode --off >/dev/null 2>&1
    # Run the actual command
    sudo -u www-data php "$NCPATH"/occ "$@";
    # Enable maintenance:mode again
    sudo -u www-data php "$NCPATH"/occ maintenance:mode --on >/dev/null 2>&1
else
    sudo -u www-data php "$NCPATH"/occ "$@";
fi
}

# Backwards compatibility (2020-10-08)
occ_command() {
nextcloud_occ "$@";
}

occ_command_no_check() {
nextcloud_occ_no_check "$@";
}

# example: is_app_enabled documentserver_community
is_app_enabled() {
if nextcloud_occ app:list | sed '/Disabled/,$d' | awk '{print$2}' | tr -d ':' | sed '/^$/d' | grep -q "^$1$"
then
    return 0
else
    return 1
fi
}

#example: is_app_installed documentserver_community
is_app_installed() {
if nextcloud_occ app:list | grep -wq "$1"
then
    return 0
else
    return 1
fi
}

install_and_enable_app() {
# Download and install $1
if ! is_app_installed "$1"
then
    print_text_in_color "$ICyan" "Installing $1..."
    # nextcloud_occ not possible here because it uses check_command and will exit if nextcloud_occ fails
    installcmd="$(nextcloud_occ_no_check app:install "$1")"
    if grep 'dependencies are not fulfilled' <<< "$installcmd"
    then
    msg_box "The $1 app could not be installed.
It's probably not compatible with $(nextcloud_occ -V).

You can try to install the app manually after the script has finished,
or when a new version of the app is released with the following command:

'sudo -u www-data php ${NCPATH}/occ app:install $1'"
    rm -Rf "$NCPATH/apps/$1"
    else
        # Enable $1 if it's installed but not enabled
        if is_app_installed "$1"
        then
            if ! is_app_enabled "$1"
            then
                nextcloud_occ_no_check app:enable "$1"
                chown -R www-data:www-data "$NC_APPS_PATH"
            fi
        fi
    fi
else
    print_text_in_color "$ICyan" "It seems like $1 is installed already, trying to enable it..."
    nextcloud_occ_no_check app:enable "$1"
fi
}

download_verify_nextcloud_stable() {
# Check the current Nextcloud version
while [ -z "$NCVERSION" ]
do
    print_text_in_color "$ICyan" "Fetching the latest Nextcloud version..."
    NCVERSION=$(curl -s -m 900 $NCREPO/ | sed --silent 's/.*href="nextcloud-\([^"]\+\).zip.asc".*/\1/p' | sort --version-sort | tail -1)
    STABLEVERSION="nextcloud-$NCVERSION"
    print_text_in_color "$IGreen" "$NCVERSION"
done

# Download the file
# Use GitHub releases for NC 32+ for faster downloads
# GitHub URL format: https://github.com/nextcloud-releases/server/releases/download/v{VERSION}/nextcloud-{VERSION}.tar.bz2
if [ "${NCVERSION%%.*}" -ge 32 ]
then
    NCGITHUB="https://github.com/nextcloud-releases/server/releases/download"
    DOWNLOAD_URL="$NCGITHUB/v$NCVERSION/$STABLEVERSION.tar.bz2"
    print_text_in_color "$ICyan" "Downloading $STABLEVERSION from GitHub releases (faster)..."
else
    DOWNLOAD_URL="$NCREPO/$STABLEVERSION.tar.bz2"
    print_text_in_color "$ICyan" "Downloading $STABLEVERSION..."
fi

rm -f "$HTML/$STABLEVERSION.tar.bz2"
cd $HTML
if network_ok
then
    curl -fSLO --retry 3 "$DOWNLOAD_URL"
else
    msg_box "There seems to be an issue with your network, please try again later.\nThis script will now exit."
    exit 1
fi
# Checksum of the downloaded file
print_text_in_color "$ICyan" "Checking SHA256 checksum..."
mkdir -p "$SHA256_DIR"
curl_to_dir "$NCREPO" "$STABLEVERSION.tar.bz2.sha256" "$SHA256_DIR"
SHA256SUM="$(tail "$SHA256_DIR"/"$STABLEVERSION".tar.bz2.sha256 | awk '{print$1}' | head -1)"
if ! echo "$SHA256SUM" "$STABLEVERSION.tar.bz2" | sha256sum -c
then
    msg_box "The SHA256 checksums of $STABLEVERSION.tar.bz2 didn't match, please try again."
    exit 1
fi
# integrity of the downloaded file
print_text_in_color "$ICyan" "Checking GPG integrity..."
install_if_not gnupg
mkdir -p "$GPGDIR"
curl_to_dir "$NCREPO" "$STABLEVERSION.tar.bz2.asc" "$GPGDIR"
chmod -R 600 "$GPGDIR"
gpg --keyserver hkp://keyserver.ubuntu.com --recv-keys "$OpenPGP_fingerprint"
gpg --verify "$GPGDIR/$STABLEVERSION.tar.bz2.asc" "$HTML/$STABLEVERSION.tar.bz2"
rm -r "$SHA256_DIR"
rm -r "$GPGDIR"
rm -f releases
}

# call like: download_script folder_variable name_of_script
# e.g. download_script MENU additional_apps
# Use it for functions like download_static_script
download_script() {
    download_script_function_in_use=yes
    rm -f "${SCRIPTS}/${2}.sh" "${SCRIPTS}/${2}.php" "${SCRIPTS}/${2}.py"
    if ! { curl_to_dir "${!1}" "${2}.sh" "$SCRIPTS" || curl_to_dir "${!1}" "${2}.php" "$SCRIPTS" || curl_to_dir "${!1}" "${2}.py" "$SCRIPTS"; }
    then
        print_text_in_color "$IRed" "Downloading ${2} failed"
        sleep 2
        msg_box "Script failed to download. Please run: \
'sudo curl -sLO ${!1}/${2}.sh|php|py' and try again.

If it still fails, please report this issue to: $ISSUES."
        exit 1
    fi
}

# call like: run_script folder_variable name_of_script
# e.g. run_script MENU additional_apps
# Use it for functions like run_script STATIC
run_script() {
    rm -f "${SCRIPTS}/${2}.sh" "${SCRIPTS}/${2}.php" "${SCRIPTS}/${2}.py"
    if download_script "${1}" "${2}"
    then
        if [ -f "${SCRIPTS}/${2}".sh ]
        then
            bash "${SCRIPTS}/${2}.sh"
            rm -f "${SCRIPTS}/${2}.sh"
        elif [ -f "${SCRIPTS}/${2}".php ]
        then
            php "${SCRIPTS}/${2}.php"
            rm -f "${SCRIPTS}/${2}.php"
        elif [ -f "${SCRIPTS}/${2}".py ]
        then
            install_if_not python3
            python3 "${SCRIPTS}/${2}.py"
            rm -f "${SCRIPTS}/${2}.py"
        fi
    else
        print_text_in_color "$IRed" "Running ${2} failed"
        sleep 2
        msg_box "Script failed to execute. Please run: \
'sudo curl -sLO ${!1}/${2}.sh|php|py' and try again.

If it still fails, please report this issue to: $ISSUES."
        exit 1
    fi
}

# Run any script in ../main
# call like: run_main_script name_of_script
run_main_script() {
run_script GITHUB_REPO "${1}"
}

# Backwards compatibility (2020-10-25) Needed for update.sh to run in all VMs, even those several years old
run_static_script() {
run_script STATIC "${1}"
}

version(){
    local h t v

    [[ $2 = "$1" || $2 = "$3" ]] && return 0

    v=$(printf '%s\n' "$@" | sort -V)
    h=$(head -n1 <<<"$v")
    t=$(tail -n1 <<<"$v")

    [[ $2 != "$h" && $2 != "$t" ]]
}

version_gt() {
    local v1 v2 IFS=.
    read -ra v1 <<< "$1"
    read -ra v2 <<< "$2"
    printf -v v1 %03d "${v1[@]}"
    printf -v v2 %03d "${v2[@]}"
    [[ $v1 > $v2 ]]
}
remove_collabora_docker() {
    # Check if Collabora is previously installed
    # If yes, then stop and prune the docker container
    docker_prune_this 'collabora/code'
    # Revoke LE
    SUBDOMAIN=$(input_box_flow "Please enter the subdomain you are using for Collabora, e.g: office.yourdomain.com")
    if [ -f "$CERTFILES/$SUBDOMAIN/cert.pem" ]
    then
        yes no | certbot revoke --cert-path "$CERTFILES/$SUBDOMAIN/cert.pem"
        REMOVE_OLD="$(find "$LETSENCRYPTPATH/" -name "$SUBDOMAIN*")"
        for remove in $REMOVE_OLD
            do rm -rf "$remove"
        done
    fi
    # Remove Apache2 config
    if [ -f "$SITES_AVAILABLE/$SUBDOMAIN.conf" ]
    then
        a2dissite "$SUBDOMAIN".conf
        restart_webserver
        rm -f "$SITES_AVAILABLE/$SUBDOMAIN.conf"
    fi
    # Disable RichDocuments (Collabora App) if activated
    if is_app_installed richdocuments
    then
        nextcloud_occ app:remove richdocuments
    fi
    # Remove trusted domain
    remove_from_trusted_domains "$SUBDOMAIN"
}

remove_onlyoffice_docker() {
    # Check if Onlyoffice is previously installed
    # If yes, then stop and prune the docker container
    docker_prune_this 'onlyoffice/documentserver'
    # Revoke LE
    SUBDOMAIN=$(input_box_flow "Please enter the subdomain you are using for OnlyOffice, e.g: office.yourdomain.com")
    if [ -f "$CERTFILES/$SUBDOMAIN/cert.pem" ]
    then
        yes no | certbot revoke --cert-path "$CERTFILES/$SUBDOMAIN/cert.pem"
        REMOVE_OLD="$(find "$LETSENCRYPTPATH/" -name "$SUBDOMAIN*")"
        for remove in $REMOVE_OLD
            do rm -rf "$remove"
        done
    fi
    # Remove Apache2 config
    if [ -f "$SITES_AVAILABLE/$SUBDOMAIN.conf" ]
    then
        a2dissite "$SUBDOMAIN".conf
        restart_webserver
        rm -f "$SITES_AVAILABLE/$SUBDOMAIN.conf"
    fi
    # Disable onlyoffice if activated
    if is_app_installed onlyoffice
    then
        nextcloud_occ app:remove onlyoffice
    fi
    # Remove trusted domain
    remove_from_trusted_domains "$SUBDOMAIN"
}

# Remove all office apps
remove_all_office_apps() {
    # remove OnlyOffice-documentserver if installed
    if is_app_installed documentserver_community
    then
        nextcloud_occ app:remove documentserver_community
    fi

    # Disable OnlyOffice App if installed
    if is_app_installed onlyoffice
    then
        nextcloud_occ app:remove onlyoffice
    fi

    # remove richdocumentscode-documentserver if installed
    if is_app_installed richdocumentscode
    then
        nextcloud_occ app:remove richdocumentscode
    fi

    # Disable RichDocuments (Collabora App) if installed
    if is_app_installed richdocuments
    then
        nextcloud_occ app:remove richdocuments
    fi
}

# Check if docker is installed
is_docker_running() {
    docker ps -a > /dev/null 2>&1
}

# Check if specific docker image is present
is_image_present() {
    [[ $(docker images -q "$1") ]]
}

# Check if old docker exists
# FULL NAME e.g. ark74/nc_fts or containrrr/watchtower or collabora/code or 'nextcloud/aio-imaginary'
does_this_docker_exist() {
is_docker_running && is_image_present "$1";
}

install_docker() {
if ! is_docker_running
then
    is_process_running dpkg
    is_process_running apt
    print_text_in_color "$ICyan" "Installing Docker CE..."
    apt-get update -q4 & spinner_loading
    install_if_not curl
    curl -fsSL https://get.docker.com | sh
fi

# Set overlay2
if ! [ -f /etc/docker/daemon.json ] || ! grep -q '"storage-driver": "overlay2"' /etc/docker/daemon.json
then
    cat << OVERLAY2 > /etc/docker/daemon.json
{
  "storage-driver": "overlay2"
}
OVERLAY2

    # Only restart if changed
    systemctl daemon-reload
    systemctl restart docker.service
fi
}

# Remove all dockers excluding one
# docker_prune_except_this fts_esror 'Full Text Search'
docker_prune_except_this() {
print_text_in_color "$ICyan" "Checking if there are any old images and removing them..."
DOCKERPS=$(docker ps -a | grep -v "$1" | awk 'NR>1 {print $1}')
if [ "$DOCKERPS" != "" ]
then
    if yesno_box_yes "Do you want to remove old Docker instance(s)... ($DOCKERPS)? Please note that we will not remove $1 ($2)."
    then
        docker stop "$(docker ps -a | grep -v "$1" | awk 'NR>1 {print $1}')"
        docker container prune -f
        docker image prune -a -f
        docker volume prune -f
    else
        msg_box "OK, this script will now exit, but there's still leftovers to cleanup. You can run it again at any time."
        exit
    fi
fi
}

# Remove selected Docker image
# docker_prune_this 'collabora/code' 'onlyoffice/documentserver' 'ark74/nc_fts' 'imaginary'
docker_prune_this() {
if does_this_docker_exist "$1"
then
    if yesno_box_yes "Do you want to remove $1?"
    then
        CONTAINER="$(docker container ls -a | grep "$1" | awk '{print $1}' | tail -1)"
        if [ -z "$CONTAINER" ]
        then
            # Special solution if the container name is scrambled, then search for the actual name instead 
            CONTAINER="$(docker container ls -a | grep "$2" | awk '{print $1}' | tail -1)"
        fi
        docker stop "$CONTAINER"
        docker rm "$CONTAINER"
        docker image prune -a -f
        docker system prune -a -f
    else
        msg_box "OK, this script will now exit, but there's still leftovers to cleanup. You can run it again at any time."
        exit
    fi
fi
}

# Remove selected Docker volume
# docker_prune_volume ''
docker_prune_volume() {
if docker volume ls | grep -q "$1$"
then
    msg_box "Removing old Docker volume: $1
You will be given the option to abort when you hit OK."
    any_key "Press any key to continue. Press CTRL+C to abort"
    docker volume rm "$1" -f
fi
}

# Stop and remove selected docker-compose items (containers, networks, volumes) by up.
# docker-compose_down "$OPNSDIR/docker-compose.yml" (absolute path to docker-compose.yml)
docker-compose_down() {
if [ -f "$1" ]
then
    cd "$(dirname "$1")"
    if is_this_installed docker-compose
    then
        docker-compose down --volumes --rmi all
    else
        docker compose down --volumes --rmi all
    fi
    # Remove leftovers
    docker system prune -a -f
else
    echo "Non-existing docker-compose file path, skipping..."
fi
}

# Update specific Docker image
# docker_update_specific 'vaultwarden' 'Vaultwarden' (docker conainter name = $1, the name in text = $2)
docker_update_specific() {
if is_docker_running && docker ps -a --format "{{.Names}}" | grep -q "^$1$"
then
    if docker run --rm --name temporary_watchtower -v /var/run/docker.sock:/var/run/docker.sock ghcr.io/nicholas-fedor/watchtower:latest --cleanup --run-once "$1"
    then
        print_text_in_color "$IGreen" "$2 docker image just got updated!"
        echo "Docker image just got updated! We just updated $2 docker image automatically! $(date +%Y%m%d)" >> "$VMLOGS"/update.log
    fi
fi
}
# docker-compose_update 'fulltextsearch-elasticsearch' 'Full Text Search' "$FTSDIR"
# (docker conainter name = $1, the name in text = $2 , docker-compose directory = $3)
docker-compose_update() {
if is_docker_running && docker ps -a --format "{{.Names}}" | grep -q "^$1$"
then
    cd "$3"
    docker compose pull
    docker compose up -d --remove-orphans
    docker image prune -a -f
    print_text_in_color "$IGreen" "$2 docker image just got updated!"
    echo "Docker image just got updated! We just updated $2 docker image automatically! $(date +%Y%m%d)" >> "$VMLOGS"/update.log
fi
}

# countdown 'message looks like this' 10
countdown() {
print_text_in_color "$ICyan" "$1"
secs="$(($2))"
while [ $secs -gt 0 ]; do
   echo -ne "$secs\033[0K\r"
   sleep 1
   : $((secs--))
done
}

print_text_in_color() {
printf "%b%s%b\n" "$1" "$2" "$Color_Off"
}
# Prettify Json files
# $1 = json input
prettify_json() {
    local JSON_INPUT
    JSON_INPUT="$(echo "$1" | sed 's|\\||g' | sed 's|,"|,\\n  "|g;s|":|": |g;s|{"|{\n  "|;s|"}|"\n}|')"
    echo -e "$JSON_INPUT"
}

# Example:
# notify_admin_gui \
# "Subject" \
# "Message"
#
# nextcloud_occ_no_check notification:generate -l "$2" "$admin" "$1"
notify_admin_gui() {
local NC_USERS
local user
local admin
if ! is_app_enabled notifications
then
    print_text_in_color "$IRed" "The notifications app isn't enabled - unable to send notifications"
    return 1
fi

print_text_in_color "$ICyan" "Posting notification to users that are admins, this might take a while..."
send_mail "$1" "$2"
if [ -z "${NC_ADMIN_USER[*]}" ]
then
    NC_USERS=$(nextcloud_occ_no_check user:list | sed 's|^  - ||g' | sed 's|:.*||')
    mapfile -t NC_USERS <<< "$NC_USERS"
    for user in "${NC_USERS[@]}"
    do
        if nextcloud_occ_no_check user:info "$user" | cut -d "-" -f2 | grep -x -q " admin"
        then
            NC_ADMIN_USER+=("$user")
        fi
    done
fi

for admin in "${NC_ADMIN_USER[@]}"
do
    print_text_in_color "$IGreen" "Posting '$1' to: $admin"
    nextcloud_occ_no_check notification:generate -l "$2" "$admin" "$(hostname -f): $1"
done
}

# Use this to send system mails
# e.g.: send_mail "subject" "text"
send_mail() {
    local RECIPIENT
    if [ -f /etc/msmtprc ]
    then
        RECIPIENT=$(grep "recipient=" /etc/msmtprc)
        RECIPIENT="${RECIPIENT##*recipient=}"
        if [ -n "$RECIPIENT" ]
        then
            print_text_in_color "$ICyan" "Sending '$1' to $RECIPIENT"
            if echo -e "$2" | mail -s "NcVM: $(hostname -f) - $1" "$RECIPIENT"
            then
                return 0
            fi
        fi
    fi
    return 1
}


check_php() {
print_text_in_color "$ICyan" "Getting current PHP-version..."
GETPHP="$(php -v | grep -m 1 PHP | awk '{print $2}' | cut -d '-' -f1)"

if [ -z "$GETPHP" ]
then
    print_text_in_color "$IRed" "Can't find proper PHP version, aborting..."
    exit 1
fi

if grep 7.0 <<< "$GETPHP" >/dev/null 2>&1
then
   export PHPVER=7.0
elif grep 7.1 <<< "$GETPHP" >/dev/null 2>&1
then
   export PHPVER=7.1
elif grep 7.2 <<< "$GETPHP" >/dev/null 2>&1
then
   export PHPVER=7.2
elif grep 7.3 <<< "$GETPHP" >/dev/null 2>&1
then
   export PHPVER=7.3
elif grep 7.4 <<< "$GETPHP" >/dev/null 2>&1
then
   export PHPVER=7.4
elif grep 8.0 <<< "$GETPHP" >/dev/null 2>&1
then
   export PHPVER=8.0
elif grep 8.1 <<< "$GETPHP" >/dev/null 2>&1
then
   export PHPVER=8.1
elif grep 8.2 <<< "$GETPHP" >/dev/null 2>&1
then
   export PHPVER=8.2
elif grep 8.3 <<< "$GETPHP" >/dev/null 2>&1
then
   export PHPVER=8.3
elif grep 8.4 <<< "$GETPHP" >/dev/null 2>&1
then
   export PHPVER=8.4
elif grep 8.5 <<< "$GETPHP" >/dev/null 2>&1
then
   export PHPVER=8.5
elif grep 8.6 <<< "$GETPHP" >/dev/null 2>&1
then
   export PHPVER=8.6
fi

# Export other PHP variables based on PHPVER
export PHP_FPM_DIR=/etc/php/$PHPVER/fpm
export PHP_INI=$PHP_FPM_DIR/php.ini
export PHP_POOL_DIR=$PHP_FPM_DIR/pool.d
export PHP_MODS_DIR=/etc/php/"$PHPVER"/mods-available

# Show version
print_text_in_color "$IGreen" PHPVER="$PHPVER"
}

#============================================================
# CORE FUNCTIONS 
#============================================================




function web_user(){

if [ -z "$1" ]; then 
    echo "Add Web domain with user isolated with default storoge of 30gb"
    echo "usage:"
    echo "web_user usename domain"
else
	   if [ -z "$2" ]; then
         echo "domain name si needed"
    else

nusr="${1}"
domain="${2}"

avail=/etc/nginx/sites-available/${nusr}
hosts="/etc/hosts"
lp="/home/${nusr}/public_html/index.html"

#create new user
#sudo useradd -m -s $(which bash) -G sudo <USERNAME>
#id -u "${nusr}" >/dev/null 2>&1 || sudo useradd -m -c "${nusr}" "${nusr}" -s /bin/bash
id -u "${nusr}" >/dev/null 2>&1 || sudo useradd -m -c "${nusr}" "${nusr}" -G www-data



sudo chgrp www-data /home/${nusr}/public_html/

sudo chmod 755 /home/${nusr}
sudo chmod 750 /home/${nusr}/public_html
sudo chmod +s /home/${nusr}/public_html


#sudo printf "[global]\nbreak-system-packages = true\n" | sudo tee --append ${pipconf}
#
## Set Cavern Enviroment
sudo mkdir -p /home/${nusr}/.config/pip/

sudo chown -R ${nusr}:${nusr} /home/${nusr}/.config

if [[ ! -f /home/${nusr}/.config/pip/pip.conf ]]; then	
   printf "[global] \nbreak-system-packages = true\n" | sudo tee --append  /home/${nusr}/.config/pip/pip.conf
fi

sudo chown -R ${nusr}:${nusr} /home/${nusr}/.config/pip/pip.conf
sudo chmod 644 /home/${nusr}/.config/pip/pip.conf

# Add python3 path 

# TODO search the line and  add if not exists
#sudo -u ${nusr} printf "export PATH=\"\$PATH:\$HOME/.local/bin\"" >> /home/${nusr}/.bashrc

#add entry in /etc/nginx
#
## Generate $HTTP_CONF
if [ ! -f "${avail}" ]
then
    sudo touch ${avail}
    sudo cat << HTTP_CREATE | sudo tee --append ${avail}
server {
	listen 80 ;
	listen [::]:80;

	root /home/${nusr}/public_html;

	# Add index.php to the list if you are using PHP
	index index.html index.htm index.nginx-debian.html;

	server_name ${domain};

	location / {
		# First attempt to serve request as file, then
		# as directory, then fall back to displaying a 404.
		try_files \$uri \$uri/ =404;
	}

	# pass PHP scripts to FastCGI server
	#
	#location ~ \.php$ {
	#	include snippets/fastcgi-php.conf;
	#
	#	# With php-fpm (or other unix sockets):
	#	fastcgi_pass unix:/run/php/php8.4-fpm.sock;
	#	# With php-cgi (or other tcp sockets):
	#	fastcgi_pass 127.0.0.1:9000;
	#}
	# deny access to .htaccess files, if Apache's document root
	# concurs with nginx's one
	#
	#location ~ /\.ht {
	#	deny all;
	#}
}
HTTP_CREATE
fi


sudo ln -s /etc/nginx/sites-available/${nusr} /etc/nginx/sites-enabled/

sudo sed -i 's/\(^127.0.0.1.*$\)/& '${domain}'/' ${hosts}

## Generate $welcome
if [ ! -f "${lp}" ]
then
    sudo -u ${nusr} touch ${lp}
    sudo -u ${nusr} cat << HTTP_CREATE_LP | sudo tee --append ${lp}
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to ${domain}</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>
HTTP_CREATE_LP
fi


sudo chmod 744 /home/${nusr}/public_html/index.html
#quota on
#set the basic service 
sudo setquota -u "${nusr}" 28G 31G 0 0 /home
sudo quota -As -u "${nusr}"


sudo systemctl restart nginx.service

    fi
fi

}

function quota(){

    #
    # Setup quotas 
    #
    install_if_not quota
    # assume that the second disk that host homes dirs is vdb1

    uuid=$(lsblk --fs | grep -m 1 -E vdb1 | awk '{print $4}' )
    #mount_quote='defaults,user,exec,usrjquota=aquota.user,jqfmt=vfsv1,grpjquota=aquota.group' 
    mount_quote='defaults,user,exec,usrquota,grpquota' 

    sudo sed -i 's/\(^UUID='${uuid}'.*\)\(defaults\)\(.*\)/\1'${mount_quote}'\3/' ${FSTAB}

    sudo mount -o remount,rw /home && sudo quotacheck -cug /home && sudo quotaon -v /home && sudo systemctl daemon-reload

}


#function gitpub(){
#if [ -z "$1" ]; then 
#    echo "Renew pub key in git repo"
#    echo "usage:"
#    echo "gitpub usename repo flags"
#else
#    if [ -z "$2" ]; then
#        echo "repo name is needed"
#    else
#
#    user="$(whoami)"
#    ssh_dir=/home/${user}/.ssh
#    ssh_epub=${ssh_dir}/id_ed25519.pub
#
#        if [[ -f ${ssh_epub} ]]; then 
#           echo "`cat ${ssh_epub}`"
#        else
#
#            ssh-keygen -t ed25519 -C "your_email@example.com"
#            ssh-copy-id -i ~/.ssh/id_ed25519.pub -p 22 user@1.1.1.1
#            printf "no file \n"
#        fi
#    #ssh git clone ssh:// 
#    fi
#fi
#}


## bash colors
# Reset
Color_Off='\e[0m'       # Text Reset

# Regular Colors
Black='\e[0;30m'        # Black
Red='\e[0;31m'          # Red
Green='\e[0;32m'        # Green
Yellow='\e[0;33m'       # Yellow
Blue='\e[0;34m'         # Blue
Purple='\e[0;35m'       # Purple
Cyan='\e[0;36m'         # Cyan
White='\e[0;37m'        # White

# Bold
BBlack='\e[1;30m'       # Black
BRed='\e[1;31m'         # Red
BGreen='\e[1;32m'       # Green
BYellow='\e[1;33m'      # Yellow
BBlue='\e[1;34m'        # Blue
BPurple='\e[1;35m'      # Purple
BCyan='\e[1;36m'        # Cyan
BWhite='\e[1;37m'       # White

# Underline
UBlack='\e[4;30m'       # Black
URed='\e[4;31m'         # Red
UGreen='\e[4;32m'       # Green
UYellow='\e[4;33m'      # Yellow
UBlue='\e[4;34m'        # Blue
UPurple='\e[4;35m'      # Purple
UCyan='\e[4;36m'        # Cyan
UWhite='\e[4;37m'       # White

# Background
On_Black='\e[40m'       # Black
On_Red='\e[41m'         # Red
On_Green='\e[42m'       # Green
On_Yellow='\e[43m'      # Yellow
On_Blue='\e[44m'        # Blue
On_Purple='\e[45m'      # Purple
On_Cyan='\e[46m'        # Cyan
On_White='\e[47m'       # White

# High Intensity
IBlack='\e[0;90m'       # Black
IRed='\e[0;91m'         # Red
IGreen='\e[0;92m'       # Green
IYellow='\e[0;93m'      # Yellow
IBlue='\e[0;94m'        # Blue
IPurple='\e[0;95m'      # Purple
ICyan='\e[0;96m'        # Cyan
IWhite='\e[0;97m'       # White

# Bold High Intensity
BIBlack='\e[1;90m'      # Black
BIRed='\e[1;91m'        # Red
BIGreen='\e[1;92m'      # Green
BIYellow='\e[1;93m'     # Yellow
BIBlue='\e[1;94m'       # Blue
BIPurple='\e[1;95m'     # Purple
BICyan='\e[1;96m'       # Cyan
BIWhite='\e[1;97m'      # White

# High Intensity backgrounds
On_IBlack='\e[0;100m'   # Black
On_IRed='\e[0;101m'     # Red
On_IGreen='\e[0;102m'   # Green
On_IYellow='\e[0;103m'  # Yellow
On_IBlue='\e[0;104m'    # Blue
On_IPurple='\e[0;105m'  # Purple
On_ICyan='\e[0;106m'    # Cyan
On_IWhite='\e[0;107m'   # White
