# SPDX-License-Identifier: MIT
# SPDX-FileCopyrightText: Copyright 2024 SUSE LLC
# SPDX-FileCopyrightText: Copyright 2024 Richard Brown

mig_dir=/var/lib/tik/mig
snap_dir=homebk
if [ ! -d ${mig_dir} ]; then
    prun /usr/bin/mkdir -p ${mig_dir}
fi

if [ ! -z "$(ls -A ${mig_dir})" ]; then
    log "existing backup found"
    d_opt --question --no-wrap --cancel-label="No, Delete Backup" --title="Existing user backup detected" --text="These users can be restored to the new installation\n\nWould you like to use this backup?"
    oldbackupyn=$?
    log "[oldbackupyn][${oldbackupyn}]"
    if [ "${oldbackupyn}" == 0 ]; then
        skipbackup=1
        migrate=1
        log "backup skipped, migration will use existing backup"
    else
        prun-opt /usr/sbin/btrfs property set -f -ts ${mig_dir}/${snap_dir} ro false
        for subsubvol in $(prun-opt /usr/sbin/btrfs subvolume list -o ${mig_dir}/${snap_dir} --sort=path | rev | cut -f1 -d' ' | rev | sed "s/^@//"); do
            prun /usr/sbin/btrfs subvolume delete "${subsubvol}"
        done
        prun-opt /usr/sbin/btrfs subvolume delete ${mig_dir}/${snap_dir}
        prun-opt /usr/bin/rm ${mig_dir}/*.out
        prun-opt /usr/bin/rm ${mig_dir}/system-connections/*
        prun-opt /usr/bin/rmdir ${mig_dir}/system-connections
        prun-opt /usr/bin/rm ${mig_dir}/users/*
        prun-opt /usr/bin/rmdir ${mig_dir}/users
        prun-opt /usr/bin/rm ${mig_dir}/icons/*
        prun-opt /usr/bin/rmdir ${mig_dir}/icons
        prun-opt /usr/bin/rm ${mig_dir}/localtime
        prun-opt /usr/bin/rm ${mig_dir}/subgid
        prun-opt /usr/bin/rm ${mig_dir}/subuid
        prun-opt /usr/bin/rm ${mig_dir}/bluetooth/*
        prun-opt /usr/bin/rmdir ${mig_dir}/bluetooth
        prun-opt /usr/bin/rm ${mig_dir}/openvpn/*
        prun-opt /usr/bin/rmdir ${mig_dir}/openvpn
        prun-opt /usr/bin/rm -R ${mig_dir}/fprint/*
        prun-opt /usr/bin/rmdir ${mig_dir}/fprint
        prun-opt /usr/bin/rmdir ${mig_dir}/mnt
    fi
fi

get_disk

if [ -z "${skipbackup}" ]; then
        # Although Legacy Yuga didn't officially support LUKS encrypted installations,
        # some users might have nevertheless enabled encryption anyway.
        # Search for existing crypto_LUKS partitions and, if found, prompt the user
        # to unlock those so that the migration module can find existing data.
        for encrypted_partition in $(lsblk "${TIK_INSTALL_DEVICE}" -p -n -r -o ID-LINK,FSTYPE|tr -s ' ' ";"|grep ";crypto_LUKS"|cut -d\; -f1); do
            if [ -e "/dev/mapper/crypt_${encrypted_partition}" ]; then
                # Already opened for some reason... do not prompt for the passphrase
                # but ensure we will clean up afterwards
                crypt_opened="${crypt_opened} crypt_${encrypted_partition}"
            else
                (
                  # Start deckrypt in the background so they can enter their input using their gamepad
                  # The user will type on the controller to produce passphrase lines
                  /usr/bin/deckrypt -c -a
                ) & deckrypt_pid=$!
                while true; do
                    if $gui; then
                        passphrase=$(zenity --password --title="Encrypted partition (${encrypted_partition}) detected" --cancel-label="Skip") || break
                    else
                        cenity passphrase --password --title="Encrypted partition (${encrypted_partition}) detected" --cancel-label="Skip" || break
                    fi
                    if [ -n "${passphrase}" ]; then
                        echo -n "${passphrase}" | prun /usr/sbin/cryptsetup luksOpen /dev/disk/by-id/"${encrypted_partition}" crypt_"${encrypted_partition}"
                        if [ "${?}" -eq 0 ]; then
                            crypt_opened="${crypt_opened} crypt_${encrypted_partition}"
                            # Wait for the mapped device to appear
                            wait_count=0
                            while [ ! -e "/dev/mapper/crypt_${encrypted_partition}" ] && [ ${wait_count} -lt 5 ]; do
                                sleep 1
                                wait_count=$((wait_count + 1))
                            done
                            break
                        fi
                    fi
                done
                kill $deckrypt_pid
            fi
        done
    unset passphrase

    # Probe selected disk for a btrfs partition containing /usr/lib/os-release
    probe_partitions "$TIK_INSTALL_DEVICE" "btrfs" "/usr/lib/os-release"

    if [ -n "${probedpart}" ]; then
        prun /usr/bin/mkdir ${mig_dir}/mnt
        prun-opt /usr/bin/mount -o compress=zstd:1,subvol=/@/home "${probedpart}" ${mig_dir}/mnt
        if [ "${retval}" -eq 0 ]; then
            prun /usr/sbin/btrfs quota rescan -w ${mig_dir}/mnt | d --progress --title="Detected existing /home subvolume.." --pulsate --auto-close --no-cancel --width=400
            home_size=$(prun /usr/sbin/btrfs qgroup show --raw -f ${mig_dir}/mnt | grep @/home$ | awk '{print $2}')
            tik_stick_size=$(prun /usr/sbin/btrfs fi usage --raw ${mig_dir} | grep estimated | awk '{print $3}')
            if [ "${home_size}" -gt "${tik_stick_size}" ]; then
                # Not enough space to offer migration
                migrate=0
            fi
            if [ "${home_size}" -le 16384 ]; then
                # /home subvolume is empty
                migrate=0
            fi
            prun /usr/bin/umount ${mig_dir}/mnt
        else
            log "no @/home subvolume found on ${probedpart}"
            migrate=0
        fi
        prun /usr/bin/rmdir ${mig_dir}/mnt
        # partition found, /home subvolume found, no known reason to not migrate, so ask the user
        if [ -z "${migrate}" ]; then
            d_opt --question --no-wrap --title="Backup users from the existing install?" --text="These users will be restored to the new installation."
            migrateyn=$?
            if [ "${migrateyn}" == 0 ]; then
                migrate=1
            else
                migrate=0
            fi
        fi
    fi

    if [ "${migrate}" == 1 ]; then
        # We're migrating, lets go!
        prun /usr/bin/mkdir ${mig_dir}/mnt
        prun /usr/bin/mount -o compress=zstd:1,subvol=/@/home "${probedpart}" ${mig_dir}/mnt
        # Check for existing snapshot from interrupted backup and delete if it exists boo#1224824
        if [ -d ${mig_dir}/mnt/${snap_dir} ]; then
            prun /usr/sbin/btrfs subvolume delete ${mig_dir}/mnt/${snap_dir}
        fi
            prun /usr/sbin/btrfs subvolume snapshot -r ${mig_dir}/mnt ${mig_dir}/mnt/${snap_dir}
            (prun /usr/sbin/btrfs send ${mig_dir}/mnt/${snap_dir} | pv -f -F "# %b copied in %t %r" | prun /usr/sbin/btrfs receive ${mig_dir}) 2>&1 | d --progress --title="Backing up /home" --pulsate --auto-close --no-cancel --width=400
            prun /usr/sbin/btrfs subvolume delete ${mig_dir}/mnt/${snap_dir}
            # Probe for subvolumes nested beneath /home and back them up also
            if (prun-opt /usr/sbin/btrfs subvolume list -o ${mig_dir}/mnt | grep -q "ID "); then
                prun /usr/sbin/btrfs property set -f -ts ${mig_dir}/${snap_dir} ro false
                for subsubvol in $(prun-opt /usr/sbin/btrfs subvolume list -o ${mig_dir}/mnt --sort=path | rev | cut -f1 -d' ' | rev | sed 's/^@\/home//'); do
                    subsubvolname=$(basename "$subsubvol")
                    subsubdirname=$(dirname "$subsubvol")
                    prun /usr/sbin/btrfs subvolume snapshot -r ${mig_dir}/mnt/"${subsubvol}" ${mig_dir}/mnt/"${subsubvolname}"
                    (prun /usr/sbin/btrfs send ${mig_dir}/mnt/"${subsubvolname}" | pv -f -F "# %b copied in %t %r" | prun /usr/sbin/btrfs receive ${mig_dir}/${snap_dir}/"${subsubdirname}") 2>&1 | d --progress --title="Backing up containers" --pulsate --auto-close --no-cancel --width=400
                    prun /usr/sbin/btrfs subvolume delete ${mig_dir}/mnt/"${subsubvolname}"
                done
                prun /usr/sbin/btrfs property set -f -ts ${mig_dir}/${snap_dir} ro true
            fi
            prun /usr/bin/umount ${mig_dir}/mnt
            prun /usr/bin/mount -o compress=zstd:1 "${probedpart}" ${mig_dir}/mnt
            prun /usr/bin/mount -o compress=zstd:1,subvol=/@/var "${probedpart}" ${mig_dir}/mnt/var
            etcmntcmd=$(cat ${mig_dir}/mnt/etc/fstab | grep "overlay /etc" | sed 's/\/sysroot\//${mig_dir}\/mnt\//g' | sed 's/\/work-etc.*/\/work-etc ${mig_dir}\/mnt\/etc\//' | sed 's/overlay \/etc overlay/\/usr\/bin\/mount -t overlay overlay -o/')
            eval prun "$etcmntcmd"
            prun /usr/bin/awk -F'[/:]' '($3 >= 1000 && $3 != 65534)' ${mig_dir}/mnt/etc/passwd | prun /usr/bin/awk -F':' '{ $7="/bin/bash"; print };' OFS=':' | prun tee ${mig_dir}/passwd.out
            prun /usr/bin/awk -F'[/:]' '($3 >= 1000 && $3 != 65534 && $3 != 65533)' ${mig_dir}/mnt/etc/group | prun tee ${mig_dir}/group.out
            prun /usr/bin/awk -F'[/:]' '{if ($3 >= 1000 && $3 != 65534) print $1}' ${mig_dir}/mnt/etc/passwd | prun /usr/bin/grep -f - ${mig_dir}/mnt/etc/shadow | prun tee ${mig_dir}/shadow.out
            prun /usr/bin/cp -a ${mig_dir}/mnt/etc/subuid ${mig_dir}/subuid
            prun /usr/bin/cp -a ${mig_dir}/mnt/etc/subgid ${mig_dir}/subgid
            # It's not guaranteed that the system will have existing network configs, custom localtime or AccountsService
            prun-opt /usr/bin/cp -a ${mig_dir}/mnt/etc/NetworkManager/system-connections ${mig_dir}/system-connections
            prun-opt /usr/bin/cp -a ${mig_dir}/mnt/etc/localtime ${mig_dir}/localtime
            prun-opt /usr/bin/cp -a ${mig_dir}/mnt/var/lib/AccountsService/users ${mig_dir}/users
            prun-opt /usr/bin/chmod 744 ${mig_dir}/users
            prun-opt /usr/bin/cp -a ${mig_dir}/mnt/var/lib/AccountsService/icons ${mig_dir}/icons
            prun-opt /usr/bin/cp -a ${mig_dir}/mnt/var/lib/bluetooth ${mig_dir}/bluetooth
            prun-opt /usr/bin/cp -a ${mig_dir}/mnt/var/lib/fprint ${mig_dir}/fprint
            prun-opt /usr/bin/cp -a ${mig_dir}/mnt/etc/openvpn ${mig_dir}/openvpn
            prun-opt /usr/bin/umount ${mig_dir}/mnt/etc
            prun /usr/bin/umount ${mig_dir}/mnt/var
            prun /usr/bin/umount ${mig_dir}/mnt
            prun /usr/bin/rmdir ${mig_dir}/mnt
    fi

    # Close eventual mapped LUKS devices
    if [ -n "${crypt_opened}" ]; then
        for mapped_partition in ${crypt_opened}; do
            if [ -e "/dev/mapper/crypt_${encrypted_partition}" ]; then
                # We are going to replace the encrypted partition anyway, so if
                # we're unable to gracefully close the device after 5 seconds,
                # just give up (hence the prun-opt usage)
                wait_count=0
                while ! prun-opt /usr/sbin/cryptsetup luksClose /dev/mapper/"${mapped_partition}" && [ ${wait_count} -lt 5 ]; do
                    sleep 1
                    wait_count=$((wait_count + 1))
                done
            fi
        done
    fi

fi