#!/usr/bin/env bash

mount_upgrade_ubm() {
    local PATH_UBM="/${1%/*}"
    local FILE_UBM="${1##*/}"
    mount | grep -q "on ${PATH_UBM}" && return 0
    [[ -n ${PATH_UBM} && ! -d ${PATH_UBM} ]] && install -dm750 ${PATH_UBM}
    if [[ -w ${PATH_UBLINUX_DATA_UPGRADE} && -w ${PATH_UBM} ]]; then
	umount ${PATH_UBM} 2>/dev/null
	mount -B ${PATH_UBLINUX_DATA_UPGRADE} ${PATH_UBM} || echo -e "\nWARNING: Failed to mount real update folder.\nThe update will only apply to the current session\n"
    else 
	echo -e "\nWARNING: Failed to mount real update folder\n"
    fi    
}

umount_upgrade_ubm() {
    local PATH_UBM="/${1%/*}"
    [[ -d ${PATH_UBM} ]] && umount ${PATH_UBM} 2>/dev/null
}

upgrade_ubm() {
    SHADOW_CLEAN() {
    # Удалить все тени файловой системы которые ссылаются на файлы ветки модуля
	for ShadowFile in $(cd ${changesDir}; find * -type f -regex '.*/\.wh\..*' ); do
	    [[ -e /memory/bundles/${FILE_UBM}/${ShadowFile/\/.wh./\/} ]] && rm -rdf ${changesDir}/${ShadowFile}
	done
	return 0
    }
    [[ -f $1 ]] || { echo -e "\nERROR: Unable to find module to install/upgrade\n" >&2 && return 0; }
#    local PATH_UBM="/${1%/*}"
    local FILE_UBM=${1##*/}
    [[ -d ${PATH_UBLINUX_DATA_UPGRADE} ]] && local PATH_LOAD_UBM=${PATH_UBLINUX_DATA_UPGRADE} || local PATH_LOAD_UBM=${PATH_UPGRADE}
    # Находим модуль с аналогичным именем, игнорируем версию и архитектуру
    # Ищем модули по шаблону, где версия дистрибутива: 010-core-2204-1-x86_64.ubm
#    FIND_UBM=$(find ${PATH_UBLINUX_BASE}/ ${PATH_UBLINUX_MODULES}/ ${PATH_UBLINUX_DATA_MODULES}/ \
#	-regextype sed -regex ".*/$(sed 's/-[0-9:]\{0,4\}[0-9]\{4\}-[0-9]\{1,4\}-.*\.ubm//' <<< ${FILE_UBM})-[0-9:]\{0,4\}[0-9]\{4\}-[0-9]\{1,4\}-.*\.ubm.*")
    # Ищем модули по шаблону, где версия ядра: 001-linux-5.17.6-2-x86_64.ubm
#    [[ -n ${FIND_UBM} ]] || FIND_UBM=$(find ${PATH_UBLINUX_BASE}/ ${PATH_UBLINUX_MODULES}/ ${PATH_UBLINUX_DATA_MODULES}/ \
#	-regextype sed -regex ".*/$(sed 's/-[0-9:]\{0,4\}[0-9.]\{5,8\}-[0-9]\{1,4\}-.*\.ubm//' <<< ${FILE_UBM})-[0-9:]\{0,4\}[0-9.]\{5,8\}-[0-9]\{1,4\}-.*\.ubm.*")
    # Ищем модули по шаблону, где версия пакета: 001-package-name-123:12.34.5678-2-x86_64.ubm
#    [[ -n ${FIND_UBM} ]] || FIND_UBM=$(find ${PATH_UBLINUX_BASE}/ ${PATH_UBLINUX_MODULES}/ ${PATH_UBLINUX_DATA_MODULES}/ \
#	-regextype sed -regex ".*/$(sed 's/-[0-9:]\{0,4\}[0-9.]\{1,10\}-[0-9]\{1,4\}-.*\.ubm//' <<< ${FILE_UBM})-[0-9:]\{0,4\}[0-9.]\{1,10\}-[0-9]\{1,4\}-.*\.ubm.*")
    FIND_UBM=$(find ${PATH_UBLINUX_BASE}/ ${PATH_UBLINUX_MODULES}/ ${PATH_UBLINUX_DATA_MODULES}/ \
	-regextype sed -regex ".*/$(sed 's/-[0-9:]\{0,4\}[0-9.]\{1,10\}-[0-9]\{1,4\}-.*\.ubm//' <<< ${FILE_UBM})-[0-9:]\{0,4\}[0-9.]\{1,10\}-[0-9]\{1,4\}-.*\.ubm.*")
    if [[ -n ${FIND_UBM} ]]; then
    # Модуль найден, выполняем обновление
	# Найденные модули попытаться отключить
	for ITEM_UBM in ${FIND_UBM}; do
	    if [[ ${ITEM_UBM%/*} =~ .*/base$ ]]; then 
		ubmunload -n -v ${ITEM_UBM} 2>/dev/null
	    elif [[ ${UPGRADE_KILL_APP} != "no" ]]; then
		ubmunload -n -v -k ${ITEM_UBM} 2>/dev/null
	    else
		ubmunload -n -v ${ITEM_UBM} 2>/dev/null
	    fi
    	    if losetup -ln --raw -O BACK-FILE | grep -q "/${ITEM_UBM##*/}$"; then
    	        NOT_RM_ITEM_UBM=${ITEM_UBM}
    	        echo "remove=${ITEM_UBM}" >> ${F_UPGRADE_CONF}
    	        echo -e "\nWARNING: Failed to unload the module '${ITEM_UBM##*/}'" >&2
    	        echo -e "Because it is used by another application" >&2
    	        echo -e "The module will try to be unloaded and removed after a reboot.\n" >&2
    	    else
	        rm -f ${ITEM_UBM} 2>/dev/null  || echo -e "\nERROR: Failed to remove module\n" >&2
    	    fi    		
	    [[ -z ${NOT_RM_ITEM_UBM} ]] && LAST_ITEM_UBM=${ITEM_UBM} || LAST_ITEM_UBM=${NOT_RM_ITEM_UBM}
	done
        if [[ -w ${LAST_ITEM_UBM%/*} ]]; then
        # Перемещаем в каталог где был обнаружен модуль
            PATH_LOAD_UBM_NEW=${LAST_ITEM_UBM%/*}
            mv -n ${PATH_LOAD_UBM}/${FILE_UBM} ${PATH_LOAD_UBM_NEW}/
            if [[ -f ${PATH_LOAD_UBM}/${FILE_UBM} ]]; then 
        	mv -n ${PATH_LOAD_UBM}/${FILE_UBM} ${PATH_LOAD_UBM_NEW}/${FILE_UBM}.upgrade
        	[[ -f ${PATH_LOAD_UBM}/${FILE_UBM} ]] || FILE_UBM="${FILE_UBM}.upgrade"
    	    fi
        elif [[ -w ${PATH_UBLINUX_DATA_MODULES} ]]; then 
        # Если каталог не доступен, то перемещаем пользователю
            PATH_LOAD_UBM_NEW=${PATH_UBLINUX_DATA_MODULES}
            mv -n ${PATH_LOAD_UBM}/${FILE_UBM} ${PATH_LOAD_UBM_NEW}/
            if [[ -f ${PATH_LOAD_UBM}/${FILE_UBM} ]]; then 
        	mv -n ${PATH_LOAD_UBM}/${FILE_UBM} ${PATH_LOAD_UBM_NEW}/${FILE_UBM}.upgrade
        	[[ -f ${PATH_LOAD_UBM}/${FILE_UBM} ]] || FILE_UBM="${FILE_UBM}.upgrade"
    	    fi
        else
            echo -e "\nWARNING: Failed copy upgrade module '${PATH_LOAD_UBM}/${FILE_UBM}' to real upgrade folder\n" >&2
        fi
        if [[ -f ${PATH_LOAD_UBM}/${FILE_UBM} ]]; then
            PATH_LOAD_UBM_NEW=${PATH_LOAD_UBM}
            echo "upgrade=${LAST_ITEM_UBM%/*}/${FILE_UBM}" >> ${F_UPGRADE_CONF}
        fi
        ubmload -n ${PATH_LOAD_UBM_NEW}/${FILE_UBM} && SHADOW_CLEAN || echo "WARNING: Failed to load module ' ${PATH_LOAD_UBM_NEW}/${FILE_UBM}', will attempt to load after reboot" >&2
    else
    # Модуль не найден, новая установка
	if [[ -w ${PATH_UBLINUX_BASE} && ${FILE_UBM} =~ ^[0-9]{3}-.* ]]; then
	    PATH_LOAD_UBM_NEW=${PATH_UBLINUX_BASE}
	    mv -f $1 ${PATH_LOAD_UBM_NEW}/
	elif [[ -w ${PATH_UBLINUX_DATA_MODULES} ]]; then
	    PATH_LOAD_UBM_NEW=${PATH_UBLINUX_DATA_MODULES}
	    mv -f $1 ${PATH_LOAD_UBM_NEW}/
	else
	    PATH_LOAD_UBM_NEW=${PATH_LOAD_UBM}
	    echo "install=${PATH_UBLINUX_DATA_MODULES}/${FILE_UBM}" >> ${F_UPGRADE_CONF}
	    echo -e "\nWARNING: Failed to copy new module to upgrade folder\n" >&2
	fi
	ubmload -n ${PATH_LOAD_UBM_NEW}/${FILE_UBM} && SHADOW_CLEAN || echo "WARNING: Failed to load module '${PATH_LOAD_UBM_NEW}/${FILE_UBM}'" >&2
    fi
}

remove_ubm() {
    for ITEM_UBM in $(find ${PATH_UBLINUX_BASE}/ ${PATH_UBLINUX_MODULES}/ ${PATH_UBLINUX_DATA_MODULES}/ ${PATH_UPGRADE}/ -name "${1##*/}" -o -name "${1##*/}.upgrade*" ); do
	#echo "Module files that are currently used by processes:"
	ubmunload -n -v -k ${ITEM_UBM} 2>/dev/null
        PREFIX=$(grep ' / aufs' /proc/mounts | cut -f2 -d= | tr ',' ' ' | cut -f1 -d' ')
        if ls /sys/fs/aufs/si_${PREFIX}/br[0-9]* 2>/dev/null | xargs cat | sed "s/=.*//" | grep -q "/${ITEM_UBM##*/}$"; then	
#        if aufs-n --raw '$bname_source' | grep -q "^${ITEM_UBM##*/}$"; then
	    # Если не удалось от отмонтировать, по причине занятости файлов, то
	    #  - Удалить все пакеты этого модуля через pacman, это наложит тени на все файлы модуля
	    rm -f /var/lib/pacman/db.lck
	    LIST_PKG_DEL=$(cd /memory/bundles/${ITEM_UBM##*/}/var/lib/pacman/local; find * -maxdepth 0 -type d -regextype sed -regex ".*-[0-9:]\{0,4\}[0-9.]\{5,8\}-[0-9]\{1,4\}.*" | sed "s|-[0-9:]\{0,4\}[0-9.]\{5,8\}-[0-9]\{1,4\}.*||")
#    	    pacman -Rs --noconfirm --noprogressbar ${LIST_PKG_DEL} 2>/dev/null
    	    pacman -Rs --noconfirm ${LIST_PKG_DEL} #2>/dev/null
    	    touch /var/lib/pacman/db.lck
	    # Получить все пакеты обыкновенные
		# find * -maxdepth 0 -type d -regextype sed -regex ".*-[0-9:]\{0,4\}[0-9.]\{5,8\}-[0-9]\{1,4\}.*" | sed "s|-[0-9:]\{0,4\}[0-9.]\{5,8\}-[0-9]\{1,4\}.*||"
	    # Получить все пакеты модулей
		# find * -maxdepth 0 -type d -regextype sed -regex ".*-[0-9:]\{0,4\}[0-9]\{4\}-[0-9]\{1,4\}.*" | sed "s|-[0-9:]\{0,4\}[0-9]\{4\}-[0-9]\{1,4\}.*||"
    	    echo "remove=${ITEM_UBM}" >> ${F_UPGRADE_CONF}
	    echo -e "\nWARNING: Failed to unload the module ${ITEM_UBM##*/}"
    	    echo -e "Because it is used by another application"
    	    echo -e "The module will try to be unloaded and removed after a reboot.\n"
    	else
	    rm -f ${ITEM_UBM} 2>/dev/null || echo -e "\nERROR: Failed to remove module\n"
    	fi
    	sync
    done
}

notify_send() {
    #Detect the name of the display in use
    local DISPLAY=":$(ls /tmp/.X11-unix/* | sed 's#/tmp/.X11-unix/X##' | head -n 1)"
    #Detect the user using such display
    local USER=$(who | grep "(${DISPLAY})" | cut -d" " -f1 | head -n 1) #"
    #Detect the id of the user
    local UID=$(id -u ${USER})
    sudo -u ${USER} DISPLAY=${DISPLAY} DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/${UID}/bus notify-send "$@"
}

    # Check execute in chroot
    grep -i ".*pacman.*--sysroot /memory/aufs-ubm.*" <<< ${SUDO_COMMAND} \
	&& echo -e "WARNING: Module update cannot be run from chroot or container!" && exit 0

    PATH_BIN_TMP="/tmp/ubm-upgrade.bin"
    if [[ ! -d ${PATH_BIN_TMP} ]]; then 
	mkdir -p ${PATH_BIN_TMP}
	cp -t ${PATH_BIN_TMP}/ /usr/bin/ubm /usr/bin/ubmload /usr/bin/ubmunload /usr/bin/aufs-n
    fi
    PATH="${PATH_BIN_TMP}:${PATH}"
    [[ -f $(dirname $0)/ubm ]] && . $(dirname $0)/ubm || . ${PATH_BIN_TMP}/ubm || . $(command -v ubm) || exit 1

    . /usr/lib/ublinux/os-config
    [[ -f ${SYSCONF}/upgrade ]] && . ${SYSCONF}/upgrade
    [[ -f ${SYSCONF}/config ]] && . ${SYSCONF}/config

    PATH_UBLINUX_BASE=$(find /memory/layer-base/*/ -maxdepth 1 -type d -name "base" | head -1)
    PATH_UBLINUX_MODULES=$(find /memory/layer-base/*/ -maxdepth 1 -type d -name "modules" | head -1)
    PATH_UBLINUX_DATA_MODULES=$(find /memory/layer-base/*/ -maxdepth 1 -type d -name "modules" | tac | head -1)
    PATH_UBLINUX_DATA_UPGRADE=$(find /memory/layer-base/*/ -maxdepth 1 -type d -name "upgrade" | head -1)
#    F_UPGRADE_CONF=$(find ${PATH_UBLINUX_DATA_UPGRADE} -maxdepth 1 -type f -name "upgrade.conf" | head -1)
    PATH_UPGRADE="/mnt/upgrade"
    F_UPGRADE_CONF="${PATH_UPGRADE}/upgrade.conf"

    # parse command action to early exit
    case "$1" in
	mount_upgrade)
	    shift
	    mount_upgrade_ubm $1
	;;
	umount_upgrade)
	    shift
	    umount_upgrade_ubm $1
	;;
	upgrade)
	    shift
	    upgrade_ubm $1
	    ubm_update_caches $@
	    rm -rdf ${PATH_BIN_TMP}
	;;
	remove)
	    shift
	    FILE_NAME=$(sed 's/-[0-9:]\{0,4\}[0-9.]\{1,10\}-[0-9]\{1,4\}-.*\.ubm//' <<< ${1##*/})
	    # Проверка, если хук вызван не удалением пакета, а удалением файла модуля, то не выполняться.
	    if ! pacman -Qq "ubm-${FILE_NAME/.ubm/}" &>/dev/null 2>&1; then
		remove_ubm $1
		ubm_update_caches $@
	    fi
	;;
    esac


#    while read -r f; do
#	UBMFILENAME="${f##*/}"
#	if [[ -e $f ]]; then
#	    echo "OK: $f"
#	    notify_send "-i 'Title-OK' 'Message'"
#	elif [[ ! -e $f ]]; then
#	    echo "NO: $f"
#	    notify_send "-i 'Title-NO' 'Message'"
#	fi
#    done

    exit 0
