#include <cstdio>
#include <Windows.h> // TODO: remove because our dll should not be platform dependant
#undef min
#undef max

#include <Core/HAL/Filesystem/Filesystem.h>
#include <Core/JulietInit.h>
#include <Core/Logging/LogManager.h>
#include <Core/Memory/MemoryArena.h>
#include <Entity/Entity.h>
#include <Entity/EntityManager.h>

// Test code
namespace Game
{
    struct Door
    {
        DECLARE_ENTITY()
        bool IsOpened;
    };
    DEFINE_ENTITY(Door);

    struct Rock
    {
        DECLARE_ENTITY()
        int Health;
    };
    DEFINE_ENTITY(Rock);

} // namespace Game

using namespace Juliet;

extern "C" JULIET_API void GameInit(GameInitParams* params)
{
    // Example allocation in GameArena
    struct GameState
    {
        float TotalTime;
        int   Score;
    };

    auto* gameState      = ArenaPushStruct<GameState>(params->GameArena);
    gameState->TotalTime = 0.0f;
    gameState->Score     = 0;

    printf("Game Arena Allocated: %p\n", static_cast<void*>(gameState));

    using namespace Game;

    // Entity Use case
    InitEntityManager(params->GameArena);
    auto& manager  = GetEntityManager();
    Door* door     = MakeEntity<Door>(manager, 10.0f, 2.0f);
    door->IsOpened = true;

    Entity*                ent       = door->Base;
    [[maybe_unused]] Door* stillDoor = DownCast<Door>(ent);
    Assert(door == stillDoor);

    Rock* rock   = MakeEntity<Rock>(manager, 1.f, 2.f);
    rock->Health = 100;
    Assert(door->Base != rock->Base);

    printf("Door is %s\n", door->IsOpened ? "Opened" : "Closed");
    printf("Rock has %d health points\n", rock->Health);
}

extern "C" JULIET_API void __cdecl GameShutdown()
{
    printf("Shutting down game...\n");

    using namespace Game;

    ShutdownEntityManager();
}

extern "C" JULIET_API void __cdecl GameUpdate([[maybe_unused]] float deltaTime)
{
    // printf("Updating game...\n");
}
