#include "DebrisSystem.h"

#include "DespawnAtComponent.h"
#include "EntityAdmin.h"
#include "PositionComponent.h"
#include "DebrisComponent.h"
#include "tracing.h"

DebrisSystem::DebrisSystem(EntityAdmin& admin)
    : m_admin(admin)
{
}

entt::entity DebrisSystem::spawn(QVector2D position, int amount, Tick despawnAt)
{
    return m_admin.spawnDebris(position, amount, despawnAt);
}

void DebrisSystem::tickDespawn(Tick currentTick)
{
	TRACE();
    std::vector<entt::entity> expired;
    m_admin.forEach<DespawnAtComponent>(
        [&expired, currentTick](entt::entity e, DespawnAtComponent& d)
        {
            if (d.tick <= currentTick)
            {
                expired.push_back(e);
            }
        });

    for (entt::entity e : expired)
    {
        m_admin.destroy(e);
    }
}

std::optional<int> DebrisSystem::consume(entt::entity entity)
{
    if (!m_admin.isValid(entity) || !m_admin.hasAll<DebrisComponent>(entity))
    {
        return std::nullopt;
    }
    int amount = m_admin.get<DebrisComponent>(entity).amount;
    m_admin.destroy(entity);
    return amount;
}

bool collectOne(EntityAdmin& admin, entt::entity entity)
{
    if (!admin.isValid(entity) || !admin.hasAll<DebrisComponent>(entity))
    {
        return false;
    }
    DebrisComponent& data = admin.get<DebrisComponent>(entity);
    if (data.amount <= 0)
    {
        return false;
    }
    --data.amount;
    if (data.amount <= 0)
    {
        admin.destroy(entity);
    }
    return true;
}

std::vector<DebrisInfo> getAllDebrisInfo(const EntityAdmin& admin)
{
    std::vector<DebrisInfo> result;
    admin.forEach<DebrisComponent>(
        [&result, &admin](entt::entity e, const DebrisComponent& sd)
        {
            result.push_back(DebrisInfo{e, admin.get<PositionComponent>(e).value, sd.amount});
        });
    return result;
}

