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 several minutes) ... "
	[ -e $tempdir/$tarball ] && zcat $tempdir/$tarball | \
		tar --extract --numeric-owner --touch --directory /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
}

mount_vfs()
{
	mount --bind /dev /root/dev
	chroot /root mount -t proc proc /proc
	chroot /root mount -t sysfs sys /sys
}

umount_vfs()
{
	umount /root/proc
	umount /root/sys
	umount /root/dev
}

create_bootconfig()
{
	DEVICE=$(basename /dev/mmcblk0)
	# if /sys/bus/mmc0\:0001/manfid = 0x000002
	#TEGRAPART="tegrapart=recovery:700:a00:800,boot:1100:1000:800,mbr:2100:200:800"
	# if manfid = 0x000011
	TEGRAPART="tegrapart=recovery:300:a00:800,boot:d00:1000:800,mbr:1d00:200:800"
	MAX_SIZE=-1
	CMDLINE_DEFAULTS="mem=512M@0 root=$volid console=tty0 ro quiet splash"
	mount_vfs

	find_boot_part()
	{
		PART=""
		for partition in $(cat /proc/partitions |grep ${1}p|sed -e 's/^[0-9 ]*//'); do
			SIZE=$(chroot /root abootimg -i /dev/$partition 2>/dev/null|sed -rn 's/^\* image size = ([0-9]+) bytes.*/\1/p')
			if [ -n "$SIZE" ] && [ "$SIZE" -gt "$MAX_SIZE" ]; then
				PART="/dev/$partition"
			fi
		done
		echo $PART
	}

	find_tegrapart_option()
	{
		for option in $(chroot /root abootimg -i $1|sed -rn 's/^\* cmdline = ()/\1/p'); do
			case $option in
			  tegrapart*)
				TEGRAPART="$option"
			  ;;
			esac
		done
		echo $TEGRAPART
	}

	TGP=$(find_tegrapart_option $(find_boot_part $DEVICE))

	CMDLINE="$TGP $CMDLINE_DEFAULTS"

	chroot /root abootimg -u $(find_boot_part $DEVICE) -c "cmdline=$CMDLINE"

	echo "MODULES=dep" >/root/usr/share/initramfs-tools/conf.d/ac100
	echo "COMPRESS=lzma" >>/root/usr/share/initramfs-tools/conf.d/ac100
	umount_vfs
}

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_vfs
	# Workaround for (LP: #1084063 and #1164071)
	[ -e /root/etc/initramfs-tools/conf.d/framebuffer ] || echo "FRAMEBUFFER=Y" >/root/etc/initramfs-tools/conf.d/framebuffer
	# make sure we remove ourself first
	chroot /root dpkg --purge ac100-tarball-installer
	chroot /root update-initramfs -u 2>/dev/null
	[ -e /root/var/lib/oem-config/run ] || touch /root/var/lib/oem-config/run
	umount_vfs
}

apply_preseed()
{
	[ -e /preseed.cfg ] && cp /preseed.cfg /root/preseed.cfg
	if [ -e /root/preseed.cfg ]; then
		mount_vfs
		chroot /root debconf-set-selections /preseed.cfg
		umount_vfs
	fi
	if [ -e /wifi.cfg ]; then
	    target=/root/etc/NetworkManager/system-connections/active_ws_connection.conf
	    cp /wifi.cfg $target
	    chmod 600 $target
	fi
}

nexus7_install()
{
	ROOTDEVICE=$(grep mmcblk0p /proc/partitions | sort -gr -k3 |awk 'NR == 1 {print $4}')
	ROOTPART=/dev/$ROOTDEVICE
	TARBALL=/root/rootfs.tar.gz

	#tune2fs -U $(uuidgen) ${ROOTPART}
	volid=$(blkid -o value -s UUID $ROOTPART)

	mount_target $ROOTPART

	clear

	[ -e $TARBALL ] || error "No tarball found on $ROOTPART, did you use the right rootfs.img ?"

	if ! $(grep -qs $ROOTPART /proc/cmdline); then
	    abootimg -u /dev/mmcblk0p2 -c "cmdline=root=$ROOTPART ro console=tty1 fbcon=rotate:1 quiet"
	    echo -n "Rebooting device with updated kernel commandline pointing to $ROOTPART for the filesystem"
		sleep 3
	    reboot
	fi

	echo -n "Preparing the root filesystem, please wait, this will take a few minutes ... "
	zcat $TARBALL | tar --extract --numeric-owner --touch --directory /root
	echo "done."

	create_fstab
	flash_kernel

	apply_preseed

	rm $TARBALL

	mkdir -p /root/var/log/installer
	cp /media-info /root/var/log/installer/
}

ac100_install()
{
	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
}

mountroot()
{
	hardware=$(cat /proc/cpuinfo |grep "^Hardware"|sed 's/^.*: //')
	case "$hardware" in
		grouper)
			nexus7_install
			;;
		*)
			ac100_install
			;;
	esac
}
