#! /usr/bin/env sh

search_media() {
	ROOT=""
	TARGET=""
	# ANYBODY STILL USING CD-ROM?
	CDROM_DEVICES=""
	BLOCK_DEVICES=""

	while test "$1"; do
		case "$1" in
			"--target"|"-t") TARGET="$2" ; shift ;;
			"--root"|"-r") ROOT="$2" ; shift ;;
			"--help"|"-h") exit 0 ;;
		esac
		shift
	done

	echo "Searching media"
	mkdir -p "$ROOT"

	while read -r x y z partition; do
		BLOCK_DEVICES="$BLOCK_DEVICES /dev/$partition"
	done < "/proc/partitions"

	for dev in $TARGET $CDROM_DEVICES $BLOCK_DEVICES; do
		if test -b "$dev"; then
			echo "Try $dev ..."
			mount -r "$dev" "$ROOT" 1>/dev/null 2>/dev/null
			if test "$?" = "0"; then
				if test -b "$TARGET"; then
					echo "Found in $TARGET"
					echo "Searching media done"
					return 0
				fi
				if test -d "$ROOT$TARGET"; then
					echo "Found in $ROOT$TARGET"
					echo "Searching media done"
					return 0
				fi
				if test -f "$ROOT$TARGET"; then
					echo "Found in $ROOT$TARGET"
					echo "Searching media done"
					return 0
				fi
				umount "$ROOT"
			fi
		fi
	done

	return 1
}

search_filesystem() {
	SEARCH_ROOTFS=""
	OVERLAY_PATH=""
	EXTRACT_PATH=""

	while test "$1"; do
		case "$1" in
			"--search"|"-s") SEARCH_ROOTFS="$2" ; shift ;;
			"--overlay"|"-o") OVERLAY_PATH="$2" ; shift ;;
			"--extract"|"-x") EXTRACT_PATH="$2" ; shift ;;
			"--help"|"-h") exit 0 ;;
		esac
		shift
	done

	if test -d "$SEARCH_ROOTFS"; then
		for fs in "$SEARCH_ROOTFS/"*; do
			echo "In $fs ..."
			if test -d "$fs"; then
				echo "Directory $fs in use"
				continue
			fi
			search_filesystem -s "$fs" -o "$OVERLAY_PATH" -x "$EXTRACT_PATH"
		done
		
		return 0
	fi

	echo "Filesystem $SEARCH_ROOTFS"

	case "$SEARCH_ROOTFS" in
		*".squashfs")
			if test "$EXTRACT_PATH"; then
				use_driver_mount "$SEARCH_ROOTFS" "$OVERLAY_PATH$SEARCH_ROOTFS"
				use_driver_directory "$OVERLAY_PATH$SEARCH_ROOTFS" "$EXTRACT_PATH"
				umount "$OVERLAY_PATH$SEARCH_ROOTFS"
				CODE="$?"
			else
				use_driver_mount "$SEARCH_ROOTFS" "$OVERLAY_PATH$SEARCH_ROOTFS"
				CODE="$?"
			fi
			;;
		*".cpio"|*".dat")
			if test "$EXTRACT_PATH"; then
				use_driver_cpio "$SEARCH_ROOTFS" "$EXTRACT_PATH"
				CODE="$?"
			else
				use_driver_cpio "$SEARCH_ROOTFS" "$OVERLAY_PATH$SEARCH_ROOTFS"
				CODE="$?"
			fi
			;;
		*)
			if test "$EXTRACT_PATH"; then
				use_driver_directory "$SEARCH_ROOTFS" "$EXTRACT_PATH"
				CODE="$?"
			else
				use_driver_directory "$SEARCH_ROOTFS" "$OVERLAY_PATH$SEARCH_ROOTFS"
				CODE="$?"
			fi
			;;
	esac

	if test "$CODE" = "0"; then
		echo "Filesystem success"
		echo "$OVERLAY_PATH$SEARCH_ROOTFS" >> "/tmp/.overlay_fs"
	else
		echo "Filesystem failed"
	fi

	return $CODE
}

use_driver_directory() {
	mkdir -p "$2"
	if cp -a -f "$1/"* "$2"; then
		return 0
	fi
	return 1
}

use_driver_mount() {
	mkdir -p "$2"
	if mount "$1" "$2"; then
		return 0
	fi
	return 1
}

use_driver_cpio() {
	mkdir -p "$2"
	cd "$2"
	if cpio -i -d -H "newc" < "$1"; then
		return 0
	fi
	cd "$OLDPWD"
	return 1
}

cheat_sheet() {
	while test "$1"; do
		case "$1" in
			"booty.search-rootfs="*) SEARCH_ROOTFS="${1##*=}" ;;
			"booty.rootfs-changes="*) ROOTFS_CHANGES="${1##*=}" ;;
			"booty.size-of-rootfs="*) SIZE_OF_ROOTFS="${1##*=}" ;;
			"booty.volume="*) echo "${1#*=}" >> /etc/.volume ;;
			"booty.use-overlayfs") USE_FILESYSTEM="OVERLAY_FS" ;;
			"booty.use-shmfs") USE_FILESYSTEM="SHMFS" ;;
			"booty.copy-to-ram"|"toram") COPY_TO_RAM="yes" ;;
			"!booty.copy-to-ram"|"!toram") COPY_TO_RAM="no" ;;
			"booty.init="*|"init="*) INIT="${1##*=}" ;;
		esac
		shift
	done
}

main() {
	for dir in "/sbin" "/usr/sbin" "/opt/sbin" "/bin" "/usr/bin" "/opt/bin"; do
		if test -x "$dir/busybox"; then
			$dir/busybox --install
			if test "$?" = "0"; then
				BUSYBOX="yes"
			fi
		fi
	done

	echo "Install /proc /sys /dev /run"

	mount -t proc none /proc
	echo "0" >/proc/sys/kernel/printk
	mount -t sysfs none /sys
	mount -t devtmpfs none /dev
	mount -t tmpfs none /run

	while read input; do
		echo "boot: $input"
		cheat_sheet $input
	done < /proc/cmdline

	if test "$SEARCH_ROOTFS" = ""; then
		SEARCH_ROOTFS="/system"
	fi

	if test "$SIZE_OF_ROOTFS" = ""; then
		SIZE_OF_ROOTFS="50%"
	fi

	if test "$COPY_TO_RAM" = ""; then
		COPY_TO_RAM="no"
	fi

	if test "$USE_FILESYSTEM" = ""; then
		USE_FILESYSTEM="SHMFS"
	fi

	# FIXME
	# NOT THIS SHIT AGAIN PLEASE
	echo "Looking up for /sys/block devices..."
	sleep 10

	if test "$BUSYBOX" = ""; then
		for nod in "/sys/block/"*; do
			dev="${nod##*/}"
			read nod < "$nod/dev"
			mknod "/dev/$dev" "b" "${nod%:*}" "${nod#*:}" 2>/dev/null
		done
	fi
	if test "$BUSYBOX" = "yes"; then
		mdev -s
		if test -f "/proc/sys/kernel/hotplug"; then
			echo "$(which mdev)" > /proc/sys/kernel/hotplug
		fi
	fi

	if search_media -t "$SEARCH_ROOTFS" -r "/media"; then
		if test "$COPY_TO_RAM" = "yes"; then
			echo "Start copying system to the RAM drive"
			mkdir -p "/mnt/toram"
			mount -t tmpfs -o "size=100%" toram "/mnt/toram"
			if test -b "$SEARCH_ROOTFS"; then
				ROOT="/mnt/toram/media"
				cp -a "/media" "$ROOT"
			elif test -d "/media$SEARCH_ROOTFS"; then
				ROOT="/mnt/toram"
				cp -r "/media$SEARCH_ROOTFS" "$ROOT"
			elif test -f "/media$SEARCH_ROOTFS"; then
				ROOT="/mnt/toram"
				cp -r "/media$SEARCH_ROOTFS" "$ROOT"
			fi
			umount "/media"
			echo "Device can be successfully unplugged now"
		fi
		if test "$COPY_TO_RAM" = "no"; then
			if test -b "$SEARCH_ROOTFS"; then
				ROOT="/media"
			elif test -d "/media$SEARCH_ROOTFS"; then
				ROOT="/media$SEARCH_ROOTFS"
			elif test -f "/media$SEARCH_ROOTFS"; then
				ROOT="/media$SEARCH_ROOTFS"
			fi
		fi
	else
		ROOT="/media$SEARCH_ROOTFS"
		echo "Fallback to boot from initramfs"
	fi

	if test "$USE_FILESYSTEM" = "SHMFS"; then
		SWITCH_ROOTFS="/newroot"

		DRIVER_PATH="/mnt/shmfs"
		mkdir -p "$DRIVER_PATH"
		mount -t tmpfs -o size=1% tmpfs "$DRIVER_PATH" # 1% enough for mounts only

		mkdir -p "$SWITCH_ROOTFS"
		mount -t tmpfs -o size="$SIZE_OF_ROOTFS" tmpfs "$SWITCH_ROOTFS"

		# TODO
		# 1. Using block devices in SHMFS (SWITCH_ROOTFS="$ROOT" if $COPY_TO_RAM = "yes")
		# 2. Extract rootfs-changes overlay (or device) to SHMFS
		echo "Searching filesystem"
		search_filesystem -s "$ROOT" -o "$DRIVER_PATH" -x "$SWITCH_ROOTFS"
		echo "Searching filesystem done"
	fi

	if test "$USE_FILESYSTEM" = "OVERLAY_FS"; then
		SWITCH_ROOTFS="/newroot"

		DRIVER_PATH="/mnt/overlay_fs"
		mkdir -p "$DRIVER_PATH"
		mount -t tmpfs -o size=100% tmpfs "$DRIVER_PATH"

		mkdir -p "$SWITCH_ROOTFS"
		mount -t tmpfs -o size="$SIZE_OF_ROOTFS" tmpfs "$SWITCH_ROOTFS"

		echo "Searching filesystem"
		if test -b "$SEARCH_ROOTFS"; then
			echo "$ROOT" > /tmp/.overlay_fs
		else
			# TODO
			# POSIX shell does alpha-numeric sorting
			# Prevent order mount: 10 100 20 30
			# Should be: 10 20 30 100
			# Reading from file is a good idea
			#while read ROOT; do
				search_filesystem -s "$ROOT" -o "$DRIVER_PATH" -x ""
			#done < /tmp/.search_rootfs
		fi
		echo "Searching filesystem done"

		while read LINE; do
			LOWERDIR="$LINE:$LOWERDIR"
		done < /tmp/.overlay_fs

		OVERLAY_LOWERDIR="${LOWERDIR%?}"

		OVERLAY_UPPERDIR="$DRIVER_PATH/rootfs-changes"
		mkdir -p "$OVERLAY_UPPERDIR"

		OVERLAY_WORK_DIR="$DRIVER_PATH/tmp"
		mkdir -p "$OVERLAY_WORK_DIR"

		if test "$OVERLAY_LOWERDIR"; then
			L="$OVERLAY_LOWERDIR"
			U="$OVERLAY_UPPERDIR"
			W="$OVERLAY_WORK_DIR"

			if test -b "$ROOTFS_CHANGES"; then
				case "$ROOTFS_CHANGES" in
					"/dev/"???*) use_driver_mount "$ROOTFS_CHANGES" "$OVERLAY_UPPERDIR" ;;
				esac
			fi
			if test -f "$ROOTFS_CHANGES"; then
				case "$ROOTFS_CHANGES" in
					*".cpio"|*".dat") use_driver_cpio "$ROOTFS_CHANGES" "$OVERLAY_UPPERDIR" ;;
				esac
			fi

			if mount -t overlay -o lowerdir="$L",upperdir="$U",workdir="$W" rootfs "$SWITCH_ROOTFS"; then
				# FIXME
				# Still works but I don't like how it works.
				# TODO
				# Move overlays to /newroot/mnt before mounting.
				# Keep initramfs is clean.
				mkdir -p "$SWITCH_ROOTFS$DRIVER_PATH"
				mount -o bind,ro "$DRIVER_PATH" "$SWITCH_ROOTFS$DRIVER_PATH"
			else
				echo "Check your /proc/config* for CONFIG_OVERLAY_FS support"
			fi
		else
			echo "No working filesystem found"
		fi
	fi

	# TODO
	# Prepare /etc/fstab
	# Do mount -a -O no_netdev
	# Instead of this dirty hack
	# while read volume; do
	#	echo "Volume: $volume"
	# done < /tmp/.volume

	if test "$INIT" = ""; then
		INIT="/sbin/init"
	fi

	if test -x "$SWITCH_ROOTFS$INIT" || test -L "$SWITCH_ROOTFS$INIT"; then
		echo "Uninstall /proc /sys /dev /run"

		umount /proc
		umount /sys
		umount /dev
		umount /run

		echo "Switching root "
		exec switch_root "$SWITCH_ROOTFS" "$INIT" < /dev/console > /dev/console 2> /dev/null
	else
		echo "Where there is a shell, there is a way..."
		exec sh
	fi
}

main "$@"
