#!/bin/bash

BUILD_THREADS="$(grep -c processor /proc/cpuinfo)"
BUILD_DIR=
BUILD_MODE=
BUILD_SYSTEM=
RUN_TESTS=1

is_installed() {
	FOUND=0

	for dep in "$@"; do
		if command -v "$dep" >/dev/null 2>/dev/null; then
			FOUND=1
			break
		fi
	done

	if [[ $FOUND -eq 0 ]]; then
		echo "Could not find (at least one of) the following dependencies: $@" >&2
		return 1
	else
		return 0
	fi
}

installed_or_exit() {
	if ! is_installed "$@"; then
		exit 1
	fi
}

get_buildsystem() {
	is_installed "ninja" && { echo "ninja"; return 0; }
	is_installed "make"  && { echo "make";  return 0; }
}

usage_and_exit() {
	cat >&2 << EOF
Usage: $0 -d DIRECTORY -m MODE [-j THREADS]
       $0 debug [-j THREADS]    ( shortcut for => $0 -d debug -m Debug [-j THREADS] )
       $0 release [-j THREADS]  ( shortcut for => $0 -d release -m Release [-j THREADS] )
       $0 snapshot [-j THREADS] ( shortcut for => $0 -d snapshot -m Snapshot [-j THREADS] )

Algorithms Library Core builder helper script.

Arguments:
 -d DIRECTORY   Build directory (relative to ALT root)
 -m MODE        'Release' or 'Debug' or 'Snapshot'
 -j THREADS     Number of build threads. Default: Number of CPU cores ($(grep -c processor /proc/cpuinfo))
 -n             Do not run tests
EOF

	exit 1
}

installed_or_exit "cmake"
installed_or_exit "make" "ninja"

# check if shortcut
ARGS_SHORTCUT=
if [[ $# -ge 1 ]] && [[ $1 == "release" || $1 == "debug" || $1 == "snapshot" ]]; then
	ARGS_SHORTCUT=1

	if [[ $1 == "release" ]]; then
		BUILD_DIR="release"
		BUILD_MODE="Release"
	elif [[ $1 == "snapshot" ]]; then
		BUILD_DIR="snapshot"
		BUILD_MODE="Snapshot"
	elif [[ $1 == "debug" ]]; then
		BUILD_DIR="debug"
		BUILD_MODE="Debug"
	fi

	shift
fi

while getopts "d:m:j:n" arg; do
	case "$arg" in
		d)
			[[ ! -z $ARGS_SHORTCUT ]] && usage_and_exit

			BUILD_DIR=${OPTARG}
			;;

		m)
			[[ ! -z $ARGS_SHORTCUT ]] && usage_and_exit

			TMP=$(echo "$OPTARG" | tr '[:upper:]' '[:lower:]')
			if [[ "$TMP" == "debug" ]]; then
				BUILD_MODE="Debug"
			elif [[ "$TMP" == "release" ]]; then
				BUILD_MODE="Release"
			elif [[ "$TMP" == "snapshot" ]]; then
				BUILD_MODE="Snapshot"
			else
				usage_and_exit
			fi
			;;

		j)
			if [[ "${OPTARG}" =~ ^[1-9][0-9]* ]]; then
				BUILD_THREADS="${OPTARG}"
			else
				usage_and_exit
			fi
			;;

		n)
			[[ ! -z $ARGS_SHORTCUT ]] && usage_and_exit

			RUN_TESTS=0
			;;

		?)
			usage_and_exit
			;;
	esac
done

if [[ -z $BUILD_DIR || -z $BUILD_MODE ]]; then
	usage_and_exit
fi


BUILD_SYSTEM=$(get_buildsystem)
[[ -L $0 ]] && SCRIPT_PATH=$(readlink $0) || SCRIPT_PATH="$0"
ROOT=$(realpath $(dirname $SCRIPT_PATH)/../..)

cd $ROOT

# show what will be done:
BUILD_DIR_SYMLINK=$([[ -L $BUILD_DIR ]] && echo "-> $(realpath $(readlink ${BUILD_DIR}))" || echo "")
cat >&2 << EOF
------------------------------------------------------------------------------
Building Algorithms Library Core from $ROOT:
 - Mode:    $BUILD_MODE
 - Into:    $ROOT/$BUILD_DIR $BUILD_DIR_SYMLINK
 - Threads: $BUILD_THREADS
 - Builder: $BUILD_SYSTEM
 - Testing: $RUN_TESTS
------------------------------------------------------------------------------
EOF

# create build dir if nonexistent
if [ ! -d "$BUILD_DIR" ] && [ ! -L "$BUILD_DIR" ]; then
	mkdir "$BUILD_DIR"
fi

# if build_dir is a link...
if [ -L "${BUILD_DIR}" ]; then
	LINK=$(readlink "${BUILD_DIR}")
	if [ ! -d ${LINK} ]; then
		mkdir -p ${LINK}
	fi
	cd ${LINK}
else
	cd "${ROOT}/${BUILD_DIR}"
fi


CMAKE_FLAGS="-DCMAKE_BUILD_TYPE=$BUILD_MODE -DCMAKE_EXPORT_COMPILE_COMMANDS=ON"
if [[ $BUILD_SYSTEM == "ninja" ]]; then
	CMAKE_FLAGS="$CMAKE_FLAGS -GNinja"
fi
cmake $CMAKE_FLAGS ${ROOT}

# build and test
if [[ $BUILD_SYSTEM == "ninja" ]]; then
	ninja -j${BUILD_THREADS} || exit 1
	if [[ $RUN_TESTS -ne 0 ]]; then
		ctest . --output-on-failure -j ${BUILD_THREADS} || exit 1
	fi
else
	make -j${BUILD_THREADS} || exit 1
	if [[ $RUN_TESTS -ne 0 ]]; then
		make test ARGS="-j${BUILD_THREADS} --output-on-failure" || exit 1
	fi
fi

