#!/bin/bash
# rsyncs a path to a remote server

# Sets Varibles that can be changed
SERVER_IP="" # IP of remote server
INPUT_PATH="" # Absolute Path to backup, remember to end with '/'
EXCLUDE_PATTERN="" #Relitive path to INPUT_PATH to Exclude, can be left as "", also end with '/' if not empty
REMOTE_USER="" # User on remote server
REMOTE_PATH= # Absolute Path on the remote server to backup to. If path has a ' ' in it dont use "" or ''

GOTIFY_IP=""
GOTIFY_PORT=""
GOTIFY_TOKEN=""

# Sets Varibles for log files
DATE=$(date +%Y-%m-%d-%H-%M-%S)
LOG_FILE="/var/log/backup-home/${DATE}.log"
TMPFS_MOUNT="/mnt/backup-tmpfs"
BACKUP_FILE="${DATE}.tar.xz"

# Pings server IP to see if it is online
ping -c 1 "$SERVER_IP" > /dev/null 2>&1

# If online run backup
if [ $? -eq 0 ]; then
        echo "$(date) Server $SERVER_IP is online" >> "$LOG_FILE"

        ## Check size of directory
        # Get Directory sizes
        INPUT_DIR_SIZE=$(du -sh $INPUT_PATH | awk '{print $1}')
        EXCLUDE_DIR_SIZE=$(du -sh $INPUT_PATH$EXCLUDE_PATTERN | awk '{print $1}')

        # Extract the numeric value and the unit
        INPUT_DIR_SIZE_NUM=${INPUT_DIR_SIZE%%[GM]}
        INPUT_DIR_UNIT=${INPUT_DIR_SIZE: -1}
        EXCLUDE_DIR_SIZE_NUM=${EXCLUDE_DIR_SIZE%%[GM]}
        EXCLUDE_DIR_UNIT=${EXCLUDE_DIR_SIZE: -1}

        # Convert both sizes to megabytes
        if [[ $INPUT_DIR_UNIT == 'G' ]]; then
            INPUT_DIR_SIZE_NUM=$((INPUT_DIR_SIZE_NUM * 1024))
        fi

        if [[ $EXCLUDE_DIR_UNIT == 'G' ]]; then
            EXCLUDE_DIR_SIZE_NUM=$((EXCLUDE_DIR_SIZE_NUM * 1024))
        fi

        # Perform the subtraction
        RESULT_DIR_SIZE=$((INPUT_DIR_SIZE_NUM - EXCLUDE_DIR_SIZE_NUM))

        # Convert the result back to gigabytes if needed
        if [[ $INPUT_DIR_UNIT == 'G' ]]; then
            RESULT_DIR_SIZE=$((RESULT_DIR_SIZE / 1024))
            RESULT_DIR_UNIT='G'
        else
            RESULT_DIR_UNIT='M'
        fi

        ## check if there is space for TMPFS

        # Check free memory and swap
        FREE_MEM_SWAP_RAW=$(free -t --si | awk 'NR==4 {print $4}') # in kilobytes
        #echo $FREE_MEM_SWAP
        if [[ $FREE_MEM_SWAP_RAW > 1048576 ]]; then # Giga
	    	FREE_MEM_SWAP=$((FREE_MEM_SWAP_RAW / 1048576))G
        elif [[ $FREE_MEM_SWAP_RAW > 1024 ]]; then # Mega
            FREE_MEM_SWAP=$((FREE_MEM_SWAP_RAW / 1024))M
        else
            FREE_MEM_SWAP=${FREE_MEM_SWAP_RAW}K
        fi

        # Extract the numeric value and the unit
        FREE_MEM_SWAP_NUM=${FREE_MEM_SWAP%%[GM]}
        FREE_MEM_SWAP_UNIT=${FREE_MEM_SWAP: -1}

		#echo $RESULT_DIR_SIZE
        # Converts Memory and Resultant to megabytes
        if [[ $RESULT_DIR_UNIT == 'G' ]]; then
        	RESULT_DIR_SIZE=$((RESULT_DIR_SIZE * 1024))
        fi
		#echo $RESULT_DIR_SIZE
		
		#echo $FREE_MEM_SWAP_NUM
        if [[ $FREE_MEM_SWAP_UNIT == 'G' ]]; then
        	FREE_MEM_SWAP_NUM=$((FREE_MEM_SWAP_NUM * 1024))
        elif [[ $FREE_MEM_SWAP_UNIT == 'K' ]]; then
        	FREE_MEM_SWAP_NUM=$((FREE_MEM_SWAP_NUM / 1024))
        fi
        #echo $FREE_MEM_SWAP_NUM

		SPACE_NEEDED=$((RESULT_DIR_SIZE * 2))
		#echo $SPACE_NEEDED

        # Compare free memory to backup dir
        if [[ $SPACE_NEEDED -lt $FREE_MEM_SWAP_NUM ]]; then
                BACKUP=true
                echo "Enough Memory for backup" >> "$LOG_FILE" 2>&1
        else
                BACKUP=false
                echo "Not Enough Memory for backup" >> "$LOG_FILE" 2>&1
        fi
        #echo $BACKUP

        ## if space mk tmpfs and backup

        if [[ $BACKUP == true ]]; then
                mkdir -p $TMPFS_MOUNT/data
                mount -t tmpfs -o size="$((RESULT_DIR_SIZE$RESULT_DIR_UNIT * 2))" tmpfs "$TMPFS_MOUNT"
                if [ $? -eq 0 ]; then
                    echo "tmpfs mounted successfully at $TMPFS_MOUNT" >> "$LOG_FILE" 2>&1

                        # copy files to backup to tmpfs
                        rsync -av "$INPUT_PATH"/. $TMPFS_MOUNT/data --exclude="$EXCLUDE_PATTERN"  >> "$LOG_FILE" 2>&1

                        # compress files to archive
                        cd $TMPFS_MOUNT
                        tar -cJf "$BACKUP_FILE" -C "$TMPFS_MOUNT" data  >> "$LOG_FILE" 2>&1
                        if [ $? -eq 0 ]; then
                        echo "Directory compressed successfully: $MOUNT_POINT/$OUTPUT_FILE"  >> "$LOG_FILE" 2>&1

                    rsync -av "$BACKUP_FILE" $REMOTE_USER@$SERVER_IP:"$REMOTE_PATH" >> "$LOG_FILE" 2>&1
                        # Log whether or not it was sucessfull
                    if [ $? -eq 0 ]; then
                        echo "$(date) Backup successful" >> "$LOG_FILE" 2>&1
                    else
                        echo "$(date) Backup failed" >> "$LOG_FILE" 2>&1
                    fi
                
                    else
                        echo "Failed to compress directory: $SOURCE_DIR"  >> "$LOG_FILE" 2>&1
                    fi
                else
                    echo "Failed to mount tmpfs at $TMPFS_MOUNT"  >> "$LOG_FILE" 2>&1
                fi

                umount $TMPFS_MOUNT
                rm -rf $TMPFS_MOUNT
        fi
# If not online report in log
else
    echo "$(date) Server $SERVER_IP is offline" >> "$LOG_FILE"
fi

# Gotify Notification
TITLE="$(hostname) backup"
PRIORITY=0
URL="http://172.16.0.6:8081/message?token=AWQy2WKQNDteu4e"
LOG_CONTENT=$(cat "$LOG_FILE")

curl -s -S --data-urlencode "title=$TITLE" --data-urlencode "message=$LOG_CONTENT" "$URL"
