#!/bin/bash

set -e

script=
name=
rebuild_flag=
binary=
arch=

initialize()
{
	case ${arch} in
		x86_64 )
		;;
		i386 )
		;;
		armv7a )
		;;
		* )
		echo "Unsupported architecture"
		exit 1
	esac

	echo "[cos setting arch] make -C src config-${arch}"
	make -C src config-${arch}

	echo "[cos executing] make -C src config init"
	make -C src init
}

build()
{
	if ! [ -r "src/.PLATFORM_ID" ]; then
		echo "Must \"cos init\" before \"cos build\"."
		exit 1
	fi

	echo "[cos executing] make -C src all"
	make -C src all
}

clean()
{
	echo "[cos executing] make -C src clean"
	make -C src clean
}

distclean()
{
	echo "[cos executing] make -C src clean"
	make -C src distclean
}

compose()
{
	if [ -z "$script" ] || [ -z "$name" ]; then
		usage
	fi

	if ! [ -e "src/composer/target/debug/compose" ]; then
		echo "Must \"cos build\" before composition. Could not find src/composer/target/debug/compose"
	exit 1
	fi

	echo "[cos executing] src/composer/target/debug/compose $script $name"
	src/composer/target/debug/compose $script $name

	local dir="system_binaries/cos_build-${name}"

	tools/build_iso.sh ${dir}/cos.img
}

compose_opt()
{
	if [ -z "$script" ] || [ -z "$name" ] || [ -z "$rebuild_flag" ]; then
		usage
	fi

	if ! [ -e "src/composer/target/debug/compose" ]; then
		echo "Must \"cos build\" before composition. Could not find src/composer/target/debug/compose"
	exit 1
	fi

	echo "[cos executing] src/composer/target/debug/compose $script $name $rebuild_flag"
	src/composer/target/debug/compose $script $name $rebuild_flag

	local dir="system_binaries/cos_build-${name}"

	tools/build_iso.sh ${dir}/cos.img
}

run()
{
	local dir="./system_binaries/cos_build-${name}"

	if [ ! -f ${dir}/cos.iso ]
	then
		echo "Cannot find cos.iso, please do compose first"
		exit 1
	fi

	local elf_type=$(readelf -h ${dir}/cos.img | grep "Class:" | awk '{print $2}')
	local machine=$(readelf -h ${dir}/cos.img | grep "Machine:" | awk '{print $2}')

	if [ "${machine}" == "ARM" ]
	then
		./tools/arm_qemurun.sh all ${dir}
		exit 0
	fi

	if [ "${elf_type}" == "ELF64" ]
	then
		tools/run.sh ${dir}/cos.iso x86_64 ${enable_nic}
	elif [ "${elf_type}" == "ELF32" ]
	then
		tools/run.sh ${dir}/cos.iso i386 ${enable_nic}
	else
		echo "Unsupported image type: ${elf_type} !"
	fi
}

debug_run()
{
	local dir="system_binaries/cos_build-${name}"
	local gdbinit="system_binaries/gdbinit"

	if [ ! -f ${dir}/cos.iso ]
	then
		echo "Cannot find cos.iso, please do compose first and check its name"
		exit 1
	fi

	if [ ! -f ${gdbinit} ]
	then
		echo "set confirm off" > ${gdbinit}
		echo "#file ${dir}/global.booter/no_interface.llbooter.global.booter" >> ${gdbinit}
		echo "file ${dir}/cos.img" >> ${gdbinit}
		echo "target remote:1234" >> ${gdbinit}
	fi

	local elf_type=$(readelf -h ${dir}/cos.img | grep "Class:" | awk '{print $2}')

	if [ "${elf_type}" == "ELF64" ]
	then
		tools/run.sh ${dir}/cos.iso x86_64 debug ${enable_nic}
	elif [ "${elf_type}" == "ELF32" ]
	then
		tools/run.sh ${dir}/cos.iso i386 debug ${enable_nic}
	else
		echo "Unsupported image type!"
	fi
}

gdb()
{
	command gdb -x ./system_binaries/gdbinit
}

usage()
{
	echo "Usage: " $0 " init <arch: [x86_64|i386|armv7a]>|build|clean|compose <script> <output name>|run <composite name> [enable-nic]|debug_run <composite name> [enable_nic]|gdb | distclean"
	exit 1
}

case $1 in
	init )
		arch=$2
		initialize
		;;
	build )
		build
		;;
	clean )
		clean
		;;
	compose )
		script=$2
		name=$3
		compose
		;;
	compose_opt )
		script=$2
		name=$3
		rebuild_flag=$4
		compose_opt
		;;
	run )
		binary=$2
		name=$2
		enable_nic=$3
		run
		;;
	debug_run )
		name=$2
		enable_nic=$3
		debug_run
		;;
	gdb )
		gdb
		;;
	distclean )
		distclean
		;;
	* )
		usage
esac
