#include <Core/Common/CoreUtils.h>
#include <Core/Memory/MemoryArena.h>
#include <cstdio>

#if JULIET_DEBUG

namespace Juliet::UnitTest
{
    void TestMemoryArena()
    {
        // 1. Core Arena Functionality
        uint8       buffer[1024];
        MemoryArena arena;
        MemoryArenaCreate(&arena, buffer, 1024);

        Assert(arena.Offset == 0);
        Assert(arena.Size == 1024);

        void* p1 = ArenaPush(&arena, 100, 16, ConstString("Test"));
        Assert(p1 != nullptr);
        Assert(arena.Offset >= 100);

        size_t marker = ArenaGetMarker(&arena);
        void*  p2     = ArenaPush(&arena, 200, 16, ConstString("Test"));
        Assert(p2 != nullptr);
        Assert(arena.Offset >= marker + 200);

        ArenaResetToMarker(&arena, marker);
        Assert(arena.Offset == marker);

        ArenaReset(&arena);
        Assert(arena.Offset == 0);

        // 2. Alignment Test
        void*                   p3    = ArenaPush(&arena, 1, 1, ConstString("Test"));
        [[maybe_unused]] size_t addr  = reinterpret_cast<size_t>(p3);
        void*                   p4    = ArenaPush(&arena, 1, 16, ConstString("Test"));
        size_t                  addr2 = reinterpret_cast<size_t>(p4);
        Assert((addr2 % 16) == 0);

        // 3. Template Helpers
        struct TestData
        {
            int   a;
            float b;
        };
        TestData* data = ArenaPushType<TestData>(&arena, ConstString("Test"));
        Assert(data != nullptr);
        data->a = 10;
        data->b = 20.0f;

        TestData* dataArray = ArenaPushArray<TestData>(&arena, 10, ConstString("Test"));
        Assert(dataArray != nullptr);

        // 4. Scratch Arena
        MemoryArena* scratch = GetScratchArena();
        Assert(scratch != nullptr);
        void* sp = ArenaPush(scratch, 100, 16, ConstString("Test"));
        Assert(sp != nullptr);
        ScratchArenaReset();
        Assert(scratch->Offset == 0);

        printf("All MemoryArena tests passed.\n");
    }
} // namespace Juliet::UnitTest

#endif
