#!/bin/bash
scriptname=$(basename ${0})
APP_NAME="Nanolx Backup (USB Helper)"

SOURCE="${1}"
UUID="${2}"
BLKD=$(blkid -U ${UUID})
MOUNT="/media/${UUID}"
LOGFILE="/var/log/${scriptname}-${UUID}-$(date '+%Y%m%d_%H%M%S').log"

_USER=$(loginctl list-sessions --no-legend | awk '/user /{print $3}' | head -n1)
[ -z "${_USER}" ] && _USER=$(who | awk '{print $1}' | head -n1)
_UID=$(id -u "${_USER}")

send_notification () {
    local title="${1}"
    local message="${2}"
    local icon="${3}"

    if [ -n "${_USER}" ] && [ -d "/run/user/${_UID}" ]; then
        sudo -u "${_USER}" \
          DISPLAY=:0 \
          XDG_RUNTIME_DIR="/run/user/${_UID}" \
          DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/${_UID}/bus \
          PATH=/usr/bin:${PATH} \
          XDG_DATA_DIRS="/usr/share/${XDG_CURRENT_DESKTOP}:/usr/share" \
          notify-send --hint=boolean:transient:false \
            -a nanolx-backup -t 20000 -i "${icon}" "${title}" "${message}"
    fi
}

kdialog_ask_pass () {
    title="${1}"
    text="${2}"

    if [ -n "${_USER}" ] && [ -d "/run/user/${_UID}" ]; then
        sudo -u "${_USER}" \
            DISPLAY=:0 \
            WAYLAND_DISPLAY=wayland-0 \
            DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/${_UID}/bus \
            PATH=/usr/bin:${PATH} \
            XDG_DATA_DIRS="/usr/share/${XDG_CURRENT_DESKTOP}:/usr/share" \
            XDG_RUNTIME_DIR=/run/user/${_UID} \
            kdialog --title "${title}" --password "${text}"
    fi
}

if [ -z "${BLKD}" ]; then
    send_notification "${APP_NAME}" "Device ${UUID} vanished/not plugged in" "dialog-error"
    exit 1
fi

mkdir -p "${MOUNT}"

if /usr/sbin/cryptsetup isLuks ${BLKD}; then
    lsusb | grep -qi "Yubico" && YUBIKEY_PRESENT=true || YUBIKEY_PRESENT=false

    if [ "${YUBIKEY_PRESENT}" = true ]; then
        PASS=$(kdialog_ask_pass "${APP_NAME}" "Enter FIDO2 PIN for encrypted disk ${BLKD}\n(${UUID}):")
        if [ $? -ne 0 ]; then
            send_notification "${APP_NAME}" "Aborted from password dialog." "dialog-error"
            exit 1
        elif [ -n "${PASS}" ]; then
            send_notification "${APP_NAME}" "PIN entered. Please touch your YubiKey to authenticate..." "dialog-information"
            echo "${PASS}" | /usr/sbin/cryptsetup --token-only open "${BLKD}" "${UUID}_luks" || \
                echo "${PASS}" | /usr/sbin/cryptsetup open "${BLKD}" "${UUID}_luks"
        else
            send_notification "${APP_NAME}" "Please touch your YubiKey to authenticate..." "dialog-information"
            /usr/sbin/cryptsetup open "${BLKD}" "${UUID}_luks"
        fi
    else
        PASS=$(kdialog_ask_pass "${APP_NAME}" "Enter passphrase for encrypted disk ${BLKD}\n(${UUID}):")
        if [ $? -ne 0 ]; then
            send_notification "${APP_NAME}" "Aborted from password dialog." "dialog-error"
            exit 1
        elif [ -n "${PASS}" ]; then
            echo "${PASS}" | /usr/sbin/cryptsetup open "${BLKD}" "${UUID}_luks"
        else
            send_notification "${APP_NAME}" "No passphrase was provided." "dialog-error"
            exit 1
        fi
    fi

    mount /dev/mapper/${UUID}_luks -orw "${MOUNT}"
    if [ $? -ne 0 ]; then
        send_notification "${APP_NAME}" "Encrypted Disk ${UUID} could not be mounted!" "dialog-error"
        exit 1
    fi
else
    mount -U "${UUID}" -orw "${MOUNT}"
    if [ $? -ne 0 ]; then
        send_notification "${APP_NAME}" "Disk ${UUID} could not be mounted!" "dialog-error"
        exit 1
    fi
fi

send_notification "${APP_NAME}" "Disk ${UUID} was plugged in, rsync'ing: ${SOURCE}..." "drive-harddisk"

rsync -aAXv --ignore-missing-args --delete "${SOURCE}" "${MOUNT}/$(basename "${SOURCE}")/" &> "${LOGFILE}"
RSYNC_STATUS=$?

umount "${MOUNT}"
rmdir "${MOUNT}"

if /usr/sbin/cryptsetup isLuks ${BLKD} ; then
    /usr/sbin/cryptsetup close ${UUID}_luks
fi

if [ ${RSYNC_STATUS} -eq 0 ]; then
    send_notification "${APP_NAME}" "All files syncronized, Drive ${UUID} may be removed." "emblem-success"
    rm -f "${LOGFILE}"
else
    send_notification "${APP_NAME}" "rsync failed with Error: ${RSYNC_STATUS} (see ${LOGFILE} for details)!" "dialog-error"
fi
