#include "HqContent.h"

#include <vector>

#include <QVBoxLayout>

#include "BarRow.h"
#include "EntityAdmin.h"
#include "HealthComponent.h"
#include "HqProxyComponent.h"
#include "IconCaption.h"
#include "ItemChipRow.h"
#include "SectionBox.h"
#include "SelectionNames.h"
#include "Simulation.h"

HqContent::HqContent(const SelectionContext& context, const SelectionRequest& request,
                     QWidget* parent)
    // The HQ is placed before the game starts and can never be deconstructed
    // (REQ-BLD-DECONSTRUCT), so it is never a construction site.
    : SelectionContent(context, std::nullopt, parent)
{
    m_hpBar = new BarRow(tr("HP"), this);

    m_stockSection = new SectionBox(tr("Building blocks"), this);
    m_stockChips   = new ItemChipRow(context, m_stockSection);
    m_stockSection->getContentLayout()->addWidget(m_stockChips);

    // HP first, as on every card that has it (REQ-UI-SELECTION-CARD, REQ-UI-HQ-PANEL).
    getRuntimeLayout()->addWidget(m_hpBar);
    getRuntimeLayout()->addWidget(m_stockSection);

    setBuildingIdentity(BuildingType::Hq, getBuildingTypeName(BuildingType::Hq));
}

void HqContent::refreshRuntime()
{
    // Not a buffer: blocks delivered by belt go straight into the global stock
    // (REQ-HQ-BELT-INPUT). Showing it here is what tells the player to route them here
    // (REQ-UI-HQ-PANEL).
    ItemChipRow::Entry stock;
    stock.itemId    = kBlockItemId;
    stock.countText = QString::number(getContext().sim->getBuildingBlocksStock());
    stock.subLine   = tr("in stock");
    m_stockChips->setEntries(std::vector<ItemChipRow::Entry>{ stock });

    // The HQ's health lives on its proxy entity, not on the building
    // (REQ-HQ-STATS, REQ-UI-HP-BARS).
    EntityAdmin& admin = getContext().sim->getAdmin();
    admin.forEach<HqProxyComponent, HealthComponent>(
        [this](entt::entity /*entity*/, const HqProxyComponent& /*proxy*/,
               const HealthComponent& health)
        {
            const double fraction = (health.maxHp > 0.0f)
                ? static_cast<double>(health.hp) / health.maxHp
                : 0.0;
            m_hpBar->setValue(fraction, tr("%1 / %2")
                .arg(static_cast<int>(health.hp + 0.5f))
                .arg(static_cast<int>(health.maxHp + 0.5f)));
        });
}
