#!/bin/sh

# Uncomment the following line to get debug info
#set -x

source /usr/local/lib/utils

SELF=$(basename $0)

# Find out the root partition number from the kernel command line
root_part=$(cat /proc/cmdline | sed -n 's|^.*root=\([^ ]*\).*|\1|p')
root_part_num=${root_part#/dev/mmcblk0p}
if [ "${root_part_num}" -eq 1 ]; then
    die 0 "recovery mode"
elif [ "${root_part_num}" = "{$root_part}" ]; then
    die 1 "${root_part} is not an SD card partition, aborting"
elif [ "${root_part_num}" -ne 2 ]; then
    die 2 "unknown partition layout, aborting"
fi
let swap_part_num=${root_part_num}+1
swap_part=/dev/mmcblk0p${swap_part_num}
let share_part_num=${swap_part_num}+1
share_part=/dev/mmcblk0p${share_part_num}

check_first_boot () {
    [ -f /.first_boot ] && die 0 "nothing to do"
    return 0
}

check_root_id () {
    [ $(id -u) -ne 0 ] && die 3 "this script must be run as root, aborting"
    return 0
}

resize_rootfs_partition () {

    # Check that the last partition is the rootfs partition
    local last_part_line=$(sgdisk -p /dev/mmcblk0 | tail -n 1)
    set ${last_part_line}
    local last_part=${1}
    if [ "${last_part}" != "${root_part_num}" ]; then
	die 4 "rootfs is not the last partition. Don't know how to expand, aborting"
    fi

    # Remove (temporarily) the rootfs partition
    sgdisk -d ${root_part_num} /dev/mmcblk0 >/dev/null 2>&1 || die 5 "cannot remove the rootfs partition, aborting"

    # Re-create the rootfs partition with a 1GB size
    sgdisk -n ${root_part_num}:0:+1G -c ${root_part_num}:rootfs /dev/mmcblk0 >/dev/null 2>&1 || die 6 "cannot resize the rootfs partition, aborting"

    # Mark the rootfs partition as bootable
    sgdisk -A ${root_part_num}:set:2 /dev/mmcblk0 >/dev/null 2>&1 || die 7 "cannot make the rootfs partition bootable, aborting"

    # Copy the primary GPT to the end of the disk
    sgdisk -e /dev/mmcblk0 >/dev/null 2>&1 || die 8 "cannot move the GPT to the end of the disk"
    sync
    return 0
}

reload_partition_table () {
    partprobe /dev/mmcblk0 >/dev/null 2>&1 || die 9 "cannot reload the partition table, aborting"
    return 0
}

resize_rootfs_filesystem () {
    rw
    resize2fs ${root_part} >/dev/null 2>&1 || die 10 "cannot resize the root filesystem, aborting"
    ro
    return 0
}

create_swap () {
    mount | grep -q ${share_part}
    if [ $? -ne 0 ]; then

	# Check that the last partition is the rootfs partition
	local last_part_line=$(sgdisk -p /dev/mmcblk0 2>/dev/null | tail -n 1)
	set ${last_part_line}
	local last_part_num=${1}
	if [ "$last_part_num" != "$root_part_num" ]; then
	    die 11 "rootfs is not the last partition. Don't know how to create the backing store partition"
	fi

	# Create an additional linux swap partition
	let swap_part_num=${last_part_num}+1
	swap_part=/dev/mmcblk0p${swap_part_num}
	sgdisk -n ${swap_part_num}:0:+128M -c ${swap_part_num}:swap -t ${swap_part_num}:8200 /dev/mmcblk0 >/dev/null 2>&1 || die 12 "cannot create the swap partition, aborting"
	sync
	partprobe /dev/mmcblk0 >/dev/null 2>&1 || die 13 "cannot reload the partition table, aborting"
	mkswap ${swap_part} >/dev/null 2>&1
	if [ $? -ne 0 ]; then
	    die 14 "cannot create swap file, aborting"
	fi
    fi
    return 0
}

enable_swap () {
    swapon -a >/dev/null 2>&1 || die 15 "cannot enable swap file, aborting"
    return 0
}

create_backing_store_partition () {
    mount | grep -q ${share_part}
    if [ $? -ne 0 ]; then

	# Check that the last partition is the swap partition
	local last_part_line=$(sgdisk -p /dev/mmcblk0 2>/dev/null | tail -n 1)
	set ${last_part_line}
	local last_part_num=${1}
	if [ "${last_part_num}" != "${swap_part_num}" ]; then
	    die 15 "rootfs is not the last partition. Don't know how to create the backing store partition"
	fi

	# Create an additional Microsoft basic data partition share partition that fills the disk
	let share_part_num=${last_part_num}+1
	share_part=/dev/mmcblk0p${share_part_num}
	sgdisk -n ${share_part_num}:0:-0 -c ${share_part_num}:share -t ${share_part_num}:0700 /dev/mmcblk0 >/dev/null 2>&1 || die 16 "cannot create the backing store partition, aborting"
	sync
    fi
    return 0
}

format_backing_store_partition () {

    # Format the backing store as FAT32
    mkfs.vfat ${share_part} >/dev/null 2>&1 || die 17 "cannot format the backing store partition"
    
    # Add file to force assembly tests 
    mount /mnt/ || die 18 "Cannot mount /mnt"
    touch /mnt/.assembly_tests || die 19 "Cannot create assembly tests run file"
    umount /mnt/ || die 20 "Cannot unmount /mnt"
    return 0
}

check_root_id
check_first_boot
notif "First boot detected!"

notif "1/8 Resize root partition"
resize_rootfs_partition

notif "2/8 Reload partition table"
reload_partition_table

notif "3/8 Resize root filsystem"
resize_rootfs_filesystem

notif "4/8 Create swap"
create_swap

notif "5/8 Enable swap"
enable_swap

notif "6/8 Create USB partition"
create_backing_store_partition

notif "7/8 Reload partition table"
reload_partition_table

notif "8/8 Format USB partition"
format_backing_store_partition

notif "First boot setup finished!"
rw
touch /.first_boot
ro
sleep 1
clear_notif
