// vim:fileencoding=utf-8:foldmethod=marker

#ifndef WAPP_ASSERT_H
#define WAPP_ASSERT_H

#include "../aliases/aliases.h"
#include "../platform/platform.h"
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>

#ifdef WAPP_PLATFORM_CPP
BEGIN_C_LINKAGE
#endif // !WAPP_PLATFORM_CPP

#define wapp_static_assert(EXPR, MSG) extern char ASSERTION_FAILED[EXPR ? 1 : -1]

#ifndef WAPP_NO_RUNTIME_ASSERT
  #define wapp_runtime_assert(EXPR, MSG) __wapp_runtime_assert(EXPR, MSG)
#else
  #define wapp_runtime_assert(EXPR, MSG)
#endif

#ifdef WAPP_DEBUG_ASSERT
  #define wapp_debug_assert(EXPR, MSG) wapp_runtime_assert(EXPR, MSG)
#else
  #define wapp_debug_assert(EXPR, MSG)
#endif

#ifdef WAPP_PLATFORM_WINDOWS
#define __wapp_runtime_assert(EXPR, MSG) do {                                       \
  __pragma(warning(push))                                                           \
  __pragma(warning(disable:4127))                                                   \
  if (!(EXPR)) {                                                                    \
  __pragma(warning(pop))                                                            \
    __runtime_assert_failed(EXPR, MSG);                                             \
  }                                                                                 \
} while(false)
#else
#define __wapp_runtime_assert(EXPR, MSG) do {                                       \
  if (!(EXPR)) {                                                                    \
    __runtime_assert_failed(EXPR, MSG);                                             \
  }                                                                                 \
} while(false)
#endif // !WAPP_PLATFORM_WINDOWS

#define __runtime_assert_failed(EXPR, MSG) do {                                     \
  fprintf(                                                                          \
    stderr,                                                                         \
    "%s:%d (In function `%s`): Assertion failed (%" PRIu32 ")\nDiagnostic: %s\n\n", \
    __FILE__, __LINE__, __func__,                                                   \
    EXPR, MSG                                                                       \
  );                                                                                \
  abort();                                                                          \
} while(false)

#ifdef WAPP_PLATFORM_CPP
END_C_LINKAGE
#endif // !WAPP_PLATFORM_CPP

#endif // !WAPP_ASSERT_H
