#!/bin/sh
set -e

root_dir=$(dirname "$0")
root_dir=$(cd "$root_dir/.." && pwd)
if [ ! -f "$root_dir/LICENSE.txt" ]; then
	echo "Couldn't find the root dir"
	exit 1
fi

if [ "$OSTYPE" = "msys" ]; then
	is_windows=y
else
	is_windows=n
fi
net_tfm="net5.0"
net_std="netstandard2.0"
net_framework_tfm="net48"
xunit_version="2.4.1"
xunit_net_tfm_version="net472"
configuration=Release
full_check=y
gen_check=y
test_code=y
pack_code=y
coverage=y

new_func() {
	echo
	echo "****************************************************************"
	echo "$1"
	echo "****************************************************************"
	echo
}

clean_dotnet_build_output() {
	dotnet clean -v:m -c $configuration "$root_dir/src/csharp/Iced.sln"
}

generator_check() {
	new_func "Run generator, verify no diff"

	dotnet run -c $configuration -p "$root_dir/src/csharp/Intel/Generator/Generator.csproj"
	git diff --exit-code
}

build_features() {
	new_func "Build one feature at a time"

	set -- \
		"DECODER" \
		"ENCODER" \
		"ENCODER;BLOCK_ENCODER" \
		"ENCODER;BLOCK_ENCODER;CODE_ASSEMBLER" \
		"ENCODER;OPCODE_INFO" \
		"INSTR_INFO" \
		"GAS" \
		"INTEL" \
		"MASM" \
		"NASM" \
		"FAST_FMT" \
		"DECODER;ENCODER;BLOCK_ENCODER;CODE_ASSEMBLER;OPCODE_INFO;INSTR_INFO;GAS;INTEL;MASM;NASM;FAST_FMT;NO_VEX" \
		"DECODER;ENCODER;BLOCK_ENCODER;CODE_ASSEMBLER;OPCODE_INFO;INSTR_INFO;GAS;INTEL;MASM;NASM;FAST_FMT;NO_EVEX" \
		"DECODER;ENCODER;BLOCK_ENCODER;CODE_ASSEMBLER;OPCODE_INFO;INSTR_INFO;GAS;INTEL;MASM;NASM;FAST_FMT;NO_XOP" \
		"DECODER;ENCODER;BLOCK_ENCODER;CODE_ASSEMBLER;OPCODE_INFO;INSTR_INFO;GAS;INTEL;MASM;NASM;FAST_FMT;NO_D3NOW" \
		"DECODER;ENCODER;BLOCK_ENCODER;CODE_ASSEMBLER;OPCODE_INFO;INSTR_INFO;GAS;INTEL;MASM;NASM;FAST_FMT;NO_VEX;NO_EVEX;NO_XOP;NO_D3NOW"
	for features in "$@"; do
		clean_dotnet_build_output
		echo
		echo "==== $features ===="
		echo
		IcedFeatureFlags="$features" dotnet build -v:m -c $configuration -p:TargetFramework=$net_std "$root_dir/src/csharp/Intel/Iced/Iced.csproj"
	done

	set -- \
		"DECODER" \
		"DECODER;ENCODER" \
		"DECODER;ENCODER;BLOCK_ENCODER" \
		"DECODER;ENCODER;BLOCK_ENCODER;CODE_ASSEMBLER" \
		"DECODER;ENCODER;OPCODE_INFO" \
		"DECODER;INSTR_INFO" \
		"DECODER;GAS" \
		"DECODER;INTEL" \
		"DECODER;MASM" \
		"DECODER;NASM" \
		"DECODER;FAST_FMT" \
		"DECODER;ENCODER;BLOCK_ENCODER;CODE_ASSEMBLER;OPCODE_INFO;INSTR_INFO;GAS;INTEL;MASM;NASM;FAST_FMT;NO_VEX" \
		"DECODER;ENCODER;BLOCK_ENCODER;CODE_ASSEMBLER;OPCODE_INFO;INSTR_INFO;GAS;INTEL;MASM;NASM;FAST_FMT;NO_EVEX" \
		"DECODER;ENCODER;BLOCK_ENCODER;CODE_ASSEMBLER;OPCODE_INFO;INSTR_INFO;GAS;INTEL;MASM;NASM;FAST_FMT;NO_XOP" \
		"DECODER;ENCODER;BLOCK_ENCODER;CODE_ASSEMBLER;OPCODE_INFO;INSTR_INFO;GAS;INTEL;MASM;NASM;FAST_FMT;NO_D3NOW" \
		"DECODER;ENCODER;BLOCK_ENCODER;CODE_ASSEMBLER;OPCODE_INFO;INSTR_INFO;GAS;INTEL;MASM;NASM;FAST_FMT;NO_VEX;NO_EVEX;NO_XOP;NO_D3NOW"
	for features in "$@"; do
		clean_dotnet_build_output
		echo
		echo "==== TEST $features ===="
		echo
		IcedFeatureFlags="$features" dotnet build -v:m -c $configuration -p:TargetFramework=$net_tfm "$root_dir/src/csharp/Intel/Iced.UnitTests/Iced.UnitTests.csproj"
	done

	clean_dotnet_build_output
}

build_test() {
	new_func "Build, test"

	dotnet build -v:m -c $configuration "$root_dir/src/csharp/Iced.sln"

	if [ "$test_code" = "y" ]; then
		if [ "$is_windows" = "y" ]; then
			echo
			echo "==== TEST (.NET Framework x64) ===="
			echo
			~/.nuget/packages/xunit.runner.console/$xunit_version/tools/$xunit_net_tfm_version/xunit.console.exe "$root_dir/src/csharp/Intel/Iced.UnitTests/bin/$configuration/$net_framework_tfm/Iced.UnitTests.dll" -noappdomain

			echo
			echo "==== TEST (.NET Framework x86) ===="
			echo
			~/.nuget/packages/xunit.runner.console/$xunit_version/tools/$xunit_net_tfm_version/xunit.console.x86.exe "$root_dir/src/csharp/Intel/Iced.UnitTests/bin/$configuration/$net_framework_tfm/Iced.UnitTests.dll" -noappdomain
		fi

		echo
		echo "==== TEST ===="
		echo
		if [ ! -d "$root_dir/src/csharp/Intel/Iced.UnitTests/bin/$configuration/$net_tfm" ]; then
			echo "Invalid tfm: $net_tfm"
			exit 1
		fi
		if [ "$coverage" = "y" ]; then
			collect_coverage=true
		else
			collect_coverage=
		fi
		# Full path needed so have to find the Windows path if this is Windows
		if [ "$is_windows" = "y" ]; then
			cov_dir=$(cygpath -wa "$root_dir")
		else
			cov_dir="$root_dir"
		fi
		dotnet test -c $configuration -f $net_tfm -p:Exclude='"[Iced]Iced.Intel.InstructionMemorySizes,[Iced]Iced.Intel.EncoderInternal.OpCodeHandlers,[Iced]Iced.Intel.InstructionInfoInternal.InfoHandlers,[Iced]Iced.Intel.MnemonicUtils,[Iced]Iced.Intel.InstructionOpCounts"' -p:ExcludeByFile="$cov_dir/src/csharp/Intel/Iced/**/*.g.cs" -p:ExcludeByAttribute='ObsoleteAttribute' -p:CollectCoverage=$collect_coverage -p:CoverletOutputFormat=lcov --no-build "$root_dir/src/csharp/Intel/Iced.UnitTests/Iced.UnitTests.csproj" -- RunConfiguration.NoAutoReporters=true RunConfiguration.TargetPlatform=X64
	fi

	if [ "$pack_code" = "y" ]; then
		echo
		echo "==== PACK ===="
		echo
		clean_dotnet_build_output
		# Don't include the IVT in the final binary
		IcedDefineConstants="IcedNoIVT" dotnet pack -v:m -c $configuration "$root_dir/src/csharp/Intel/Iced/Iced.csproj"
	fi
}

while [ "$#" -gt 0 ]; do
	case $1 in
	--quick-check) full_check=n ;;
	--no-gen-check) gen_check=n ;;
	--no-test) test_code=n ;;
	--no-pack) pack_code=n ;;
	--no-coverage) coverage=n ;;
	*) echo "Unknown arg: $1"; exit 1 ;;
	esac
	shift
done

echo
echo "=================================================="
echo ".NET build"
echo "=================================================="
echo

echo "dotnet version"
dotnet --version

if [ "$full_check" = "y" ]; then
	if [ "$gen_check" = "y" ]; then
		generator_check
	fi
	build_features
fi
build_test
