#pragma once

/**
 * \file Test.h
 * \brief File containing unit testing utilities
 */

#include <cstdlib>

namespace blitz {
namespace utils {

/**
 * \def BLITZ_TEST_SUCCESSFUL
 * \brief Used in tests to indicate that a test was successful
 */
#define BLITZ_TEST_SUCCESSFUL 0

/**
 * \def BLITZ_TEST_FAILED
 * \brief Used in tests to indicate that a test failed
 */
#define BLITZ_TEST_FAILED 1

#ifndef __FUNCTION_NAME__
#ifdef _WIN32
#define __FUNCTION_NAME__ __FUNCTION__
#else
#define __FUNCTION_NAME__ __PRETTY_FUNCTION__
#endif
#endif

/**
 * \def blitz_test_assert
 * \param ... The expression to evaluate
 * \brief Evaluates the expression and exits the program if not valid.
 * \note It works like a basic assert() but also in release mode
 */
#define blitz_test_assert(...)                                                                                                        \
	if (!static_cast<bool>(__VA_ARGS__)) {                                                                                            \
		blitz::utils::LOGAssert(#__VA_ARGS__, __FILE__, __LINE__, __FUNCTION_NAME__);                                                 \
		std::exit(BLITZ_TEST_FAILED);                                                                                                 \
	}


/**
 * \def blitz_debug_assert
 * \param ... The expression to execute
 * \brief Assertion without checks in release mode
 * \note The expression is always executed. However, in release, no checks are made !
 */
#ifdef NDEBUG
#define blitz_debug_assert(...) __VA_ARGS__
#else
#define blitz_debug_assert blitz_test_assert
#endif


/**
 * \brief Prints an error message associated with a failed assertion
 * \param expression The expression that was tested
 * \param file The file in which the assertion failed
 * \param line The line in the file in which the assertion failed
 * \param function The function in which the assertion failed
 */
void LOGAssert(const char* expression, const char* file, int line, const char* function);

}  // namespace utils
}  // namespace blitz
