# shellcheck disable=SC2148
export PATH=".:/:/usr/sbin:/usr/bin:/sbin:/bin"
export LD_LIBRARY_PATH="/lib:/lib/i386-linux-gnu:/lib64:/lib64/x86_64-linux-gnu:/lib/x86_64-linux-gnu:/usr/lib/i386-linux-gnu:/usr/lib64/x86_64-linux-gnu:/usr/lib/x86_64-linux-gnu"
export MEMORY="/memory"
export MODULES="${MEMORY}/modules"
export CHANGES_MNT="${MEMORY}/changes"
export CHANGES="${CHANGES_MNT}/changes"
export WORK="${CHANGES_MNT}/work"
export UNION="${MEMORY}/union"
export DATAMNT="${MEMORY}/data"
export SYSTEM="${MEMORY}/system"
export SHELL_IS_ENABLED="_SHELL_ENABLED_"

progress()
{
	sh -c "${1}" >/dev/null 2>&1&
	local pid="${!}"
	while :; do
		if [ -d /proc/${pid} ]; then
			echo -n "."
			sleep 0.25
		else
			echo -en " DONE!\n"
			break
		fi
	done
}
grepCmdLine()
{
	for i in `</proc/cmdline`; do egrep "^${1}|^${1}=.*" <<<${i}|cut -f2 -d=; done
	return ${?}
}
d()
{
	grepCmdLine debug >/dev/null 2>&1
	return ${?}
}
isShellEnabled()
{
	d&&echo -n "Is 'shell' bootloader variable set? "
	if grepCmdLine shell; then
		d&&echo -en "Yes\n"
		sed -i "s/_SHELL_ENABLED_/true/g" /lib/functions >/dev/null 2>&1
		echo "[!] Reloading /lib/functions"
		if . /lib/functions; then
			echo -en "Done\n"
		else
			echo -en "Failed\n"
			emergencyShell
		fi
	else
		d&&echo -en "No\n"
	fi
}
isZramEnabled()
{
	d&&echo -n "Is zram supported? "
	if [ -e /sys/block/zram0/disksize ]; then
		d&&echo -en "Yes\n"
		echo 536870912 >/sys/block/zram0/disksize
		mkswap /dev/zram0 >/dev/null 2>&1
		swapon /dev/zram0 >/dev/null 2>&1
		echo 100 >/proc/sys/vm/swappiness
	else
		d&&echo -en "No\n"
	fi
}
findData()
{
	d&&echo -n "Searching ${DISTRO} in /dev -> "
	#local from="$(grepCmdLine from)"
	for i in ${root:-/dev/[hmnsv][dmrv][0-9a-z]*}; do
		d&&echo -n "${i#/dev/} "
		mount -o ro ${i} ${DATAMNT} >/dev/null 2>&1
		sleep 0.5
		#[[ ${from} ]]&&mount ${DATAMNT}/${from} ${DATAMNT} >/dev/null 2>&1
		if [ -e ${DATAMNT}/${DISTRO}/system.sfs ]; then
			d&&echo -e "\nFound ${DISTRO} in ${i}"
			grepCmdLine fsck&&fsck ${i} >/dev/null 2>&1||true
			d&&echo -n "Is 'toram' bootloader variable set and enought RAM space? "
			if grepCmdLine toram; local a=${?}&&[[ "$(grep MemFree /proc/meminfo|awk '{print $2}')" -gt $(("$(du ${DATAMNT}|tail -n1|awk '{print $1}')"-"$(du ${DATAMNT}/changes|tail -n1|awk '{print $1}')")) ]]; then
				d&&echo -en "Yes\n"
				mkdir -p /tmp/data
				d&&echo -n "Copying to RAM "
				d&&progress "tar -c -C ${DATAMNT} --exclude ./changes -f - . | tar -xf - -C /tmp/data"
				umount -f ${DATAMNT} >/dev/null 2>&1
				#[[ ${from} ]]&&umount -f ${DATAMNT} >/dev/null 2>&1
				mv -f /tmp/data/* ${DATAMNT} >/dev/null 2>&1
				rm -rf /tmp/data >/dev/null 2>&1
			else
				d&&if [[ "${a}" != "0" ]]; then echo -ne "Not requested by bootloader or low RAM space!\n"; else echo -ne "Internal error? Trying tmpfs, so data after power-off will be erased permanently!\n"; fi
				mount -o remount,rw ${DATAMNT} >/dev/null 2>&1||true
			fi
			mount ${DATAMNT}/${DISTRO}/system.sfs ${SYSTEM} >/dev/null 2>&1
			sleep 0.5
			break
		else
			umount -f ${DATAMNT} >/dev/null 2>&1
		fi
	done
	if ! grep -q ${SYSTEM} /proc/mounts; then
		d&&echo "Can not find compatible distro!"
		emergencyShell
	fi
}
findModules()
{
	d&&echo -n "Trying to mount modules from ${DATAMNT}/${DISTRO}/modules -> "
	if ls ${DATAMNT}/${DISTRO}/modules/*.sfs >/dev/null 2>&1; then
		for i in $(find ${DATAMNT}/${DISTRO}/modules -maxdepth 1 -type f -name "*.sfs"|sort); do
			mkdir -p ${MODULES}/$(basename ${i} .sfs)
			d&&echo -n "$(basename ${i}) "
			mount ${i} ${MODULES}/$(basename ${i} .sfs) >/dev/null 2>&1
		done
		d&&echo -en "Done\n"
	else
		d&&echo -en "Failed, modules not found! Continuing...\n"
	fi
}
mountOverlay()
{
	if grep -q ${MODULES} /proc/mounts; then
		mount -t overlay -o lowerdir=${SYSTEM}:$(find ${MODULES} -mindepth 1 -maxdepth 1 | tac | tr "\n" ":" | sed -r "s/:$//"),upperdir=${CHANGES},workdir=${WORK} overlay ${UNION}
	else
		mount -t overlay -o lowerdir=${SYSTEM},upperdir=${CHANGES},workdir=${WORK} overlay ${UNION}
	fi
}
persistentChanges()
{
	if ! grepCmdLine perch&&grepCmdLine toram; then
		return
	fi
	local CHANGES T1 T2 EXISTS
	CHANGES=$DATAMNT/changes
	T1="$CHANGES/.empty"
	T2="$T1"2
	mkdir -p "$2"
	touch "$T1" 2>/dev/null && rm -f "$T1" 2>/dev/null
	if [ $? -ne 0 ]; then
		return
	fi
	d&&echo "Testing persistent changes for posix compatibility"
	touch "$T1" && ln -sf "$T1" "$T2" 2>/dev/null && \
	chmod +x "$T1" 2>/dev/null && test -x "$T1" && \
	chmod -x "$T1" 2>/dev/null && test ! -x "$T1" && \
	rm "$T1" "$T2" 2>/dev/null
	if [ $? -eq 0 ]; then
		d&&echo "Activating native persistent changes"
		mount --bind "$CHANGES" "$2" >/dev/null 2>&1
		return
	fi
	if [ -e "$CHANGES/changes.dat.0" ]; then
		d&&echo "Restoring persistent changes"
		EXISTS="true"
	else
		d&&echo "Creating new persistent changes"
		EXISTS=""
	fi
	mount.dynfilefs -f "$CHANGES/changes.dat" -s 16000 -m "$2" -p 4000 >/dev/null 2>&1
	[ ! "$EXISTS" ] && mke2fs -F -L "DATA" "$2/virtual.dat" >/dev/null 2>&1
	grepCmdLine fsck && fsck ${2}/virtual.dat >/dev/null 2>&1
	mount "$2/virtual.dat" "$2" >/dev/null 2>&1
	rm "$T1" "$T2" >/dev/null 2>&1
	rmdir "$2/lost+found" >/dev/null 2>&1
}
debugShell()
{
	if [ "$SHELL_IS_ENABLED" = "true" ]; then
		echo -e "Debug shell!\nControl+D or 'exit' to contiunue boot.\n"
		setsid cttyhack sh
	fi
}
changeRoot()
{
	cd "$1"
	umount -f /sys /proc
	cat <<eot >etc/fstab
proc /proc proc defaults 0 0
sysfs /sys sysfs defaults 0 0
devpts /dev/pts devpts gid=5,mode=620 0 0
tmpfs /dev/shm tmpfs defaults 0 0
overlay / overlay defaults 0 0
eot
	mkdir -p run
	mount -t tmpfs tmpfs run
	mkdir -p run/initramfs
	mount -o remount,ro overlay .
	pivot_root . run/initramfs
	exec chroot . init
}
emergencyShell()
{
	exec >/dev/console >&1 2>&1 <&1
	echo "Error: Please inspect '/tmp/mlb.log' file"
	export PS1="RESCUE # "
	while :; do
		echo "Rescue shell!"
		setsid cttyhack sh
	done
}
