targetpart=""
sourcepart=""
sourcedisk=""
needs_partitioning=""
checksum_file="/installer.md5"
size_file="/installer.size"
tarball=""
checksum=""
tarsize=""
tempdir=$(mktemp -d)
current_root=$(mount|grep "on / "|cut -d" " -f1)
volid=""
filesys="ext4"

error()
{
	echo "Error: ${1}"
	panic "Spawning a shell within the initramfs"
	reboot
}

get_checksum()
{
	[ -e $checksum_file ] || error "Checksum file missing"
	checksum="$(cat ${checksum_file}|sed -e 's/ .*//')"

	[ -e $size_file ] || error "Size file missing"
	tarsize="$(cat ${size_file}|sed -e 's/ .*//')c"
}

blockdev_exists()
{
	if [ -d /sys/block/${1} ];then
		return 0
	fi
	return 1
}

first_partition_has_tarball()
{
	disk=$1
	part=""

	# default partitions to look at for respective devices
	case $disk in
		sda)
			part="/dev/sda1"
			;;
		mmcblk1)
			part="/dev/mmcblk1p1"
			;;
	esac

	# make sure we are not mounted before checking
	if grep -q $part /proc/mounts;then
		umount $part
	fi

	# check if we have the right tarball
	fs=$(blkid -o value $part | tail -1)
	mount -t $fs $part $tempdir >/dev/null 2>&1

	findings=$(find $tempdir -type f -regex .*tar.gz$ -size $tarsize)

	if [ -n "$findings" ] && [ -e "$findings" ]; then
		tarball=$(basename $findings)
		sourcepart=$part
		sourcedisk=$disk
		echo "Found $tarball on $part"
		verify_tarball $tempdir/$tarball
		return 0
	else
		if grep -q $part /proc/mounts;then
			umount $part
		fi
	fi
	return 1
}

verify_tarball()
{
	path=$1
	tarball=$(basename $path)
	echo -n "Verifying $tarball please wait ... "
	mysum=$(md5sum $path|cut -d " " -f1)
	if [ "${mysum}" != "${checksum}" ]; then
		echo "failed."
		error "Checksum does not match, please get a matching tarball and .bootimg"
	fi
	echo "done."
}

find_tarball()
{
	for disk in sda mmcblk1; do
		if blockdev_exists $disk && first_partition_has_tarball $disk;then
			break
		fi
	done
	[ -n "${sourcepart}" ] || return 1
}

find_biggest_internal_part()
{
	dev=$1
	if blockdev_exists;then
		oldpart=0
		for partsize in $(ls /sys/block/${dev}/${dev}p?*/size);do 
			partition=$(basename $(echo $partsize|sed -e 's/\/size//'))
			size=$(( $(cat $partsize) /2))
			if [ $size -gt $oldpart ];then
				oldpart=$size
				targetpart=$partition
			fi
		done
	else
		error "Can not find usable partitions on ${1}"
	fi
}

find_source_and_target_devices()
{
	# what do we want to install ?
	get_checksum

	# look if the rootfs is available
	find_tarball || error "No tarball found"

	# check if we have possible external target devices
	for file in $(ls -d /sys/block/*);do
		device=$(basename $file)
		if [ "${device}" != "${sourcedisk}" ];then
			case $device in
				mmcblk1)
					targetpart=${device}p1
					needs_partitioning=$device
					;;
				sd[a-z]*)
					targetpart=${device}1
					needs_partitioning=$device
					;;
			esac
		fi
	done
	# no external devices, find biggest internal partition
	if [ -z "${targetpart}" ] ; then
		find_biggest_internal_part mmcblk0
	fi
	# if we failed with that as well, return false
	[ -z "${targetpart}" ] && return 1
	return 0
}

unmount_target()
{
	device=$1
	[ "${device}" != "${current_root}" ] || error "$device is current root device, can not install to it"
	if mount | grep -q $device;then
		umount $device || error "Target partition $device can not be unmounted"
	fi
}

mount_target()
{
	device=$1
	mount -t $filesys $device /root || error "Target partition $device can not be mounted"
}

format_target()
{
	unmount_target /dev/$targetpart
	[ -z "${needs_partitioning}" ] || partition_target_dev
	echo -n "Formatting /dev/$targetpart ... "
	mkfs.$filesys /dev/$targetpart >/dev/null 2>&1
	volid=$(blkid |grep ${targetpart}|awk '{print $2}'|tr -d [\"])
	echo "done."
}

partition_target_dev()
{
	device=$needs_partitioning
	size=$(($(($(cat /sys/block/$device/size)/2))/1000))
	echo -n "Creating /dev/$targetpart on $device ... "
	parted -s /dev/$device mklabel msdos >/dev/null 2>&1
	parted -s -a optimal /dev/$device mkpart primary 4 $size >/dev/null 2>&1
	echo "done."
}

unpack_tarball()
{
	mount_target /dev/$targetpart
	echo -n "Unpacking filesystem to /dev/$targetpart, please wait (this can take up to 30min) ... "
	[ -e $tempdir/$tarball ] && zcat $tempdir/$tarball | tar xm --numeric-owner -C /root
	echo "done."
}

create_fstab()
{
	[ -e /root/etc/fstab ] || error "File /root/etc/fstab is missing, is /root mounted ?"
	echo "none	 /proc 	proc 	nodev,noexec,nosuid 	0 	0" >/root/etc/fstab
	echo "$volid	/	$filesys	defaults,noatime,nodiratime		0	1" >>/root/etc/fstab
}

create_bootconfig()
{
	[ -e /root/boot/bootimg.cfg ] || error "File /root/boot/bootimg.cfg is missing, is /root mounted ?"
	cat <<EOF >/root/boot/bootimg.cfg
bootsize = 0x800000
pagesize = 0x800
kerneladdr = 0x10008000
ramdiskaddr = 0x11000000
secondaddr = 0x10f00000
tagsaddr = 0x10000100
name = Ubuntu Boot Img
cmdline = mem=448M@0M tegrapart=recovery:300:a00:800,boot:d00:1000:800,mbr:1d00:200:800 root=$volid quiet splash
EOF
echo "MODULES=dep" >/root/usr/share/initramfs-tools/conf.d/ac100
}

confirm_proceeding()
{
	while true
	do
		clear
		echo "Ubuntu AC100 Tarball Installer"
		echo
		case $targetpart in
			mmcblk1*|sd?*)
				echo "The installer detected that it will install to an external device,"
				echo "if you instead want to install to the internal MMC, please remove"
				echo "/dev/$targetpart and reboot with keeping $sourcepart plugged in."
				echo
				;;
		esac
		echo "If you enter Y below, all data on /dev/$targetpart will be destroyed"
		echo "and Ubuntu will be installed on it. Entering N will reboot."
		echo
		read -p "Are you sure you want to proceed? [y/n] " answer
		case $answer in
			[yY]* )
				return 0
				;;
			[nN]* )
				echo "Rebooting ..."
				reboot
				;;
			* )
				echo "Please enter Y or N"
				;;
		esac
	done
}

flash_kernel()
{
	mount --bind /dev /root/dev
	chroot /root mount -t proc proc /proc
	chroot /root mount -t sysfs sys /sys
	# make sure we remove ourself first
	chroot /root dpkg --purge ac100-tarball-installer
	chroot /root update-initramfs -u
	[ -e /root/var/lib/oem-config/run ] || touch /root/var/lib/oem-config/run
	umount /root/proc
	umount /root/sys
	umount /root/dev
}

mountroot()
{
	clear
	sleep 8
	find_source_and_target_devices || error "No target device found"
	confirm_proceeding
	format_target && unpack_tarball && create_fstab && create_bootconfig && flash_kernel

	for dir in $tempdir /root/dev /root/proc; do
		if mount | grep -q $dir;then
			umount $dir
		fi
	done
	rm -rf $tempdir
	echo "Rebooting into configuration session ..."
	sleep 3
	reboot
}
