/*********************************************************************
 * \file   Assert.hpp
 *
 * \author Romain BOULLARD
 * \date   October 2025
 *********************************************************************/
#ifndef BIGFOOT_UTILS_ASSERT_HPP
#define BIGFOOT_UTILS_ASSERT_HPP
#include <Utils/Log/LogMacros.hpp>

#if defined BIGFOOT_NOT_OPTIMIZED

#include <source_location>
#include <string>

#if defined BIGFOOT_LINUX
#include <csignal>
#endif

#if defined BIGFOOT_WINDOWS
#define BREAK                                                                                                          \
    do                                                                                                                 \
    {                                                                                                                  \
        __debugbreak();                                                                                                \
    } while (false)
#elif defined BIGFOOT_LINUX
#define BREAK                                                                                                          \
    do                                                                                                                 \
    {                                                                                                                  \
        std::raise(SIGTRAP);                                                                                           \
    } while (false)
#endif

#define ASSERT(HANDLER, p_assert, p_message, ...)                                                                      \
    do                                                                                                                 \
    {                                                                                                                  \
        constexpr std::source_location location = std::source_location::current();                                     \
        if (!(p_assert)) [[unlikely]]                                                                                  \
        {                                                                                                              \
            HANDLER::Handle(location, p_message __VA_OPT__(, ) __VA_ARGS__);                                           \
            BREAK;                                                                                                     \
        }                                                                                                              \
    } while (false)

#define SOFT_ASSERT(HANDLER, p_assert, p_message, ...)                                                                 \
    do                                                                                                                 \
    {                                                                                                                  \
        constexpr std::source_location location = std::source_location::current();                                     \
        if (!(p_assert)) [[unlikely]]                                                                                  \
        {                                                                                                              \
            HANDLER::Handle(location, p_message __VA_OPT__(, ) __VA_ARGS__);                                           \
            BREAK;                                                                                                     \
        }                                                                                                              \
    } while (false)

#define CRITICAL_ASSERT(HANDLER, p_assert, p_message, ...)                                                             \
    do                                                                                                                 \
    {                                                                                                                  \
        constexpr std::source_location location = std::source_location::current();                                     \
        if (!(p_assert)) [[unlikely]]                                                                                  \
        {                                                                                                              \
            HANDLER::Handle(location, p_message __VA_OPT__(, ) __VA_ARGS__);                                           \
            if (Bigfoot::Singleton<Bigfoot::Log>::HasInstance())                                                       \
            {                                                                                                          \
                Bigfoot::Singleton<Bigfoot::Log>::GetInstance().Flush();                                               \
            }                                                                                                          \
            BREAK;                                                                                                     \
            std::abort();                                                                                              \
        }                                                                                                              \
    } while (false)

#else
#define ASSERT(HANDLER, p_assert, p_message, ...)

#define SOFT_ASSERT(HANDLER, p_assert, p_message, ...)

#define CRITICAL_ASSERT(HANDLER, p_assert, p_message, ...)
#endif
#endif
