#! /usr/bin/env bash

################################################################################

panic()
{
	echo "ERROR: $*"
	exit 1
}

get_clang_version()
{
	local program="${1:-clang++}"
	"$program" --version | awk '
		(NR==1){
			for (i = 1; i <= NF; ++i) {
				if (tolower($i) == "version") {
					++i;
					print $i;
					break;
				}
			}
		}
	'
}

################################################################################

self_program="$(realpath "$0")" || \
  panic "realpath failed"
self_dir="$(dirname "$self_program")" || \
  panic "dirname failed"

top_dir="$self_dir/../.."

setup_file=
verbose=0
matrix_os=

while getopts vs:c: option; do
	case "$option" in
	c)
		setup_file="$OPTARG";;
	v)
		verbose=$((verbose + 1));;
	s)
		matrix_os="$OPTARG";;
	*)
		usage "invalid option $option"
		break
		;;
	esac
done
shift $((OPTIND - 1))

if [ -n "$setup_file" ]; then
	cat <<- EOF
	============================================================
	Sourcing setup file

	setup file contents:
	============================================================
	$(cat "$setup_file")
	============================================================
	EOF
	source "$setup_file" || \
	  panic "cannot source setup file $setup_file"
fi

build_options=()

build_options+=(--num-jobs 4)

# Determine whether to run demo scripts.
case "$matrix_os" in
#ubuntu-22.04|macos-12)
#ubuntu-22.04)
#ubuntu-*)
*)
	build_options+=(--demo)
	;;
esac

# Determine whether to use the hacked fmt library.
case "$matrix_os" in
macos-*|ubuntu-*)
	build_options+=(--fmt)
	;;
esac

# Determine some sanitizer settings.
build_options+=(--no-asan-detect-leaks)
build_options+=(--asan-allow-user-poisoning)
build_options+=(--ubsan-halt-on-error)
case "$matrix_os" in
ubuntu-*)
	case "$matrix_os" in
	ubuntu-22.04)
		;;
	ubuntu-20.04)
		;;
	esac
	;;
macos-*)
	build_options+=(--no-asan-allow-user-poisoning)
	build_options+=(--no-ubsan-halt-on-error)
	case "$matrix_os" in
	macos-12)
		;;
	esac
	;;
esac

if [ "$verbose" -ge 1 ]; then
	cat <<- EOF
	============================================================
	CC: $CC
	============================================================
	CXX: $CXX
	============================================================
	PATH: $PATH
	============================================================
	LD_LIBRARY_PATH: $LD_LIBRARY_PATH
	============================================================
	CMAKE_PREFIX_PATH: $CMAKE_PREFIX_PATH
	============================================================
	CPLUS_INCLUDE_PATH: $CPLUS_INCLUDE_PATH
	C_INCLUDE_PATH: $C_INCLUDE_PATH
	CPATH: $CPATH
	============================================================
	clang++ path: $(type -P clang++)
	clang++ version: $(get_clang_version clang++)
	----------
	$(clang++ --version)
	----------
	clang path: $(type -P clang)
	clang version: $(get_clang_version clang)
	----------
	$(clang --version)
	----------
	============================================================
	g++ path: $(type -P g++)
	g++ version:
	----------
	$(g++ --version)
	----------
	gcc path: $(type -P gcc)
	gcc version:
	----------
	$(gcc --version)
	----------
	============================================================
	Clang default version of C++ standard:
	$(clang++ -dM -E -x c++  /dev/null | grep -F __cplusplus)
	============================================================
	GCC default version of C++ standard:
	$(g++ -dM -E -x c++  /dev/null | grep -F __cplusplus)
	============================================================
	python path: $(type -P python)
	python2 path: $(type -P python2)
	python3 path: $(type -P python3)
	============================================================
	EOF
fi

case "$COMPILER_CXX" in
clang++)
	compiler=clang;;
g++)
	compiler=gcc;;
*)
	panic "unknown compiler";;
esac

environ=()
case "$compiler" in
gcc)
	environ+=("CC=$GCC_CC_PATH")
	environ+=("CXX=$GCC_CXX_PATH")
	;;
clang)
	environ+=("CC=$CLANG_CC_PATH")
	environ+=("CXX=$CLANG_CXX_PATH")
	;;
esac

command=(
	env "${environ[@]}"
	"$top_dir/build"
	--verbose
	--clean
	--build
	--verbose-makefile
	--no-fmt
	--debug
	--asan
	--ubsan
	"${build_options[@]}"
)
if [ "$verbose" -ge 1 ]; then
	cat <<- EOF
	============================================================
	RUNNING: ${command[*]}
	============================================================
	EOF
fi
"${command[@]}" || panic "build failed"
