#include "MultiBuildingContent.h"

#include <map>

#include <QVBoxLayout>

#include "Building.h"
#include "BuildingIconCache.h"
#include "CountRow.h"
#include "FactoryQueries.h"
#include "GameConfig.h"
#include "IconCaption.h"
#include "ItemIconCache.h"
#include "ItemTooltip.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();

    // No item list and no clear action here, even when the selection holds belt tiles:
    // both speak of belt-subsystem tiles alone, and a button acting on part of a
    // selection would be worse than no button (REQ-UI-BELT-ITEMS, REQ-UI-BELT-CLEAR).
    // Selecting the tiles by themselves aggregates them into the belt card instead
    // (REQ-UI-SELECTION-AGGREGATE).
}

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;
        }
    }

    // The block icon stands beside the total in place of the word, as it does on a build
    // button and a blueprint card (REQ-UI-MULTI-SELECTION, REQ-UI-BLOCKS-ICON). With no
    // icon file the total is the bare number, as it is there
    // (REQ-UI-BUILD-COST, REQ-UI-BLUEPRINT-CARD).
    StatRow* totalRow = new StatRow(tr("Total cost"), this);
    totalRow->setValueIcon(
        getContext().itemIcons->getInlineIcon(kBlockItemId, font()));
    totalRow->setValue(QString::number(totalCost));
    totalRow->setValueEmphasized(true);
    // The total names an item, so it explains it, and nothing here is clickable, so a
    // click says it at once (REQ-UI-ITEM-VALUE-TOOLTIP).
    ItemTooltip::attachTo(totalRow->getValueWidget(),
                          getContext().getItemTooltipContext(), kBlockItemId,
                          TooltipTrigger::Trigger::HoverAndClick);
    getRuntimeLayout()->addWidget(totalRow);
}
