#pragma once

#include <Juliet.h>
#include <Core/Common/CoreTypes.h>
#include <Core/Common/String.h>
#include <Core/Common/NonNullPtr.h>

#if JULIET_DEBUG

namespace Juliet
{
    struct Arena;
    struct MemoryBlock;

    // Arena (Struct)
    struct ArenaDebugInfo
    {
        const char*     Tag;
        size_t          Offset;
        size_t          Size;
        ArenaDebugInfo* Next;
    };

    // MemoryArena (Pool-based)
    struct ArenaAllocation
    {
        size_t           Offset;
        size_t           Size;
        String           Tag;
        ArenaAllocation* Next;
    };

    // Arena (Struct)
    void            DebugRegisterArena(NonNullPtr<Arena> arena);
    void            DebugUnregisterArena(NonNullPtr<Arena> arena);
    void            DebugArenaSetDebugName(NonNullPtr<Arena> arena, const char* name);
    bool            IsDebugInfoArena(const Arena* arena); // To prevent recursion
    void            DebugArenaFreeBlock(Arena* block); // To clear all debug infos in a block
    void            DebugArenaRemoveAllocation(Arena* block, size_t oldOffset);
    void            DebugArenaPopTo(Arena* block, size_t newPosition);
    void            DebugArenaAddDebugInfo(Arena* block, size_t size, size_t offset, const char* tag);

    // MemoryArena (Pool-based)
    void             DebugFreeArenaAllocations(MemoryBlock* blk);
    void             DebugArenaAddAllocation(MemoryBlock* blk, size_t size, size_t offset, String tag);
    void             DebugArenaRemoveLastAllocation(MemoryBlock* blk);

} // namespace Juliet

#endif
