#include "MultiBuildingContent.h"

#include <map>

#include <QVBoxLayout>

#include "Building.h"
#include "BuildingIconCache.h"
#include "ClearBeltControl.h"
#include "CountRow.h"
#include "FactoryQueries.h"
#include "GameConfig.h"
#include "SelectionNames.h"
#include "Simulation.h"
#include "StatRow.h"

namespace
{

// Size the type symbol is drawn at on a count row, matching the card header's chip.
const int kCountSymbolSizePx = 20;

}  // namespace


MultiBuildingContent::MultiBuildingContent(const SelectionContext& context,
                                           const SelectionRequest& request,
                                           QWidget* parent)
    : SelectionContent(context, std::nullopt, parent)
    , m_ids(request.buildings)
{
    // The header names the size of the selection instead of an object
    // (REQ-UI-MULTI-SELECTION).
    setIdentity(QPixmap(), tr("%1 buildings").arg(static_cast<int>(m_ids.size())));

    buildSummary();

    // A selection holding any belt-subsystem tile can still be cleared as a whole
    // (REQ-UI-BELT-CLEAR), even though the mixture is what kept it from aggregating.
    bool hasBeltTile = false;
    for (BuildingId id : m_ids)
    {
        const Building* building = findBuilding(context.sim->getFactoryState(), id);
        if (building && isBeltSubsystemType(building->type))
        {
            hasBeltTile = true;
            break;
        }
    }
    if (hasBeltTile)
    {
        getRuntimeLayout()->addWidget(new ClearBeltControl(context, m_ids, this));
    }
}

void MultiBuildingContent::buildSummary()
{
    std::map<BuildingType, int> counts;
    for (BuildingId id : m_ids)
    {
        const Building* building =
            findBuilding(getContext().sim->getFactoryState(), id);
        if (building)
        {
            counts[building->type]++;
            continue;
        }
        const ConstructionSite* site =
            findSite(getContext().sim->getFactoryState(), id);
        if (site)
        {
            counts[site->type]++;
        }
    }

    int totalCost = 0;
    for (const std::pair<const BuildingType, int>& entry : counts)
    {
        getRuntimeLayout()->addWidget(new CountRow(
            getContext().buildingIcons->getChip(buildingTypeId(entry.first),
                                                kCountSymbolSizePx),
            getBuildingTypeName(entry.first), entry.second, this));

        // Only player-placeable buildings count toward the total; the HQ and defence
        // stations are excluded (REQ-UI-MULTI-SELECTION). A construction site counts at
        // its type's full placement cost regardless of progress.
        const BuildingDef* def =
            getContext().config->buildings.findBuildingDef(entry.first);
        if (def && def->playerPlaceable)
        {
            totalCost += def->cost * entry.second;
        }
    }

    StatRow* totalRow = new StatRow(tr("Total cost"), this);
    totalRow->setValue(QString::number(totalCost));
    totalRow->setValueEmphasized(true);
    getRuntimeLayout()->addWidget(totalRow);
}
