#pragma once
#include "log/Log.h"
#include "misc/hang.h"
#include "thread/Scheduler.h"
#include "trace/StackTracer.h"

#define __call_assert_fail(...)                                                                                        \
    kerrorln(__VA_ARGS__);                                                                                             \
    StackTracer tracer;                                                                                                \
    tracer.trace();                                                                                                    \
    hang();

#define ASSERT(expr)                                                                                                   \
    do {                                                                                                               \
        if (!(expr))                                                                                                   \
        {                                                                                                              \
            Task* cur_task = Scheduler::current_task();                                                                \
            if (cur_task)                                                                                              \
            {                                                                                                          \
                __call_assert_fail("Assertion failed in task %ld at %s, line %d: %s", cur_task->id, __FILE__,          \
                                   __LINE__, #expr);                                                                   \
            }                                                                                                          \
            else { __call_assert_fail("Assertion failed at %s, line %d: %s", __FILE__, __LINE__, #expr); }             \
        }                                                                                                              \
    } while (0)

#define TODO(message)                                                                                                  \
    do {                                                                                                               \
        Task* cur_task = Scheduler::current_task();                                                                    \
        if (cur_task)                                                                                                  \
        {                                                                                                              \
            __call_assert_fail("TODO in task %ld at %s, line %d: %s", cur_task->id, __FILE__, __LINE__, message);      \
        }                                                                                                              \
        else { __call_assert_fail("TODO at %s, line %d: %s", __FILE__, __LINE__, message); }                           \
    } while (0)

#ifdef ___weird_hack_to_put_something_at_end_of_file
#undef ___weird_hack_to_put_something_at_end_of_file
#endif