#include "BufferedBuildingContent.h"

#include <vector>

#include <QVBoxLayout>

#include "Building.h"
#include "BufferSection.h"
#include "BuildingTarget.h"
#include "FactoryQueries.h"
#include "ProductionSection.h"
#include "RecipeSummaryRow.h"
#include "SelectionNames.h"
#include "Simulation.h"

namespace
{

std::vector<RecipeSummaryRow::Amount> toAmounts(const std::map<std::string, int>& map)
{
    std::vector<RecipeSummaryRow::Amount> amounts;
    amounts.reserve(map.size());
    for (const std::pair<const std::string, int>& entry : map)
    {
        amounts.push_back(RecipeSummaryRow::Amount{ entry.first, entry.second });
    }
    return amounts;
}

}  // namespace


BufferedBuildingContent::BufferedBuildingContent(const SelectionContext& context,
                                                 BuildingId id, QWidget* parent)
    : SelectionContent(context, asConstructionSite(context, id), parent)
    , m_id(id)
{
    // The summary is configuration -- what the building will do -- so it sits with the
    // selection control and is shown for a construction site too (REQ-UI-RECIPE-SUMMARY).
    m_recipeSummary = new RecipeSummaryRow(context.itemIcons, this);
    getConfigurationLayout()->addWidget(m_recipeSummary);

    m_buffers = new BufferSection(context, this);
    m_production = new ProductionSection(this);
    getRuntimeLayout()->addWidget(m_buffers);
    getRuntimeLayout()->addWidget(m_production);
}

void BufferedBuildingContent::refreshConfiguration()
{
    const BuildingTarget target = resolveBuildingTarget(getContext(), m_id);
    if (!target.isValid())
    {
        // Gone under the card. SelectionPanel rebuilds on the same refresh; this only
        // has to avoid reading it.
        return;
    }

    setBuildingIdentity(target.type, getBuildingTypeName(target.type));

    const CycleInfo cycle = getCycleInfo(target);
    m_recipeSummary->setSummary(toAmounts(cycle.perCycleInputs),
                                toAmounts(cycle.perCycleOutputs),
                                cycle.durationSeconds);

    refreshControls(target);
}

void BufferedBuildingContent::refreshRuntime()
{
    const BuildingTarget target = resolveBuildingTarget(getContext(), m_id);
    if (!target.building)
    {
        return;
    }

    setProductionStatusSlot(*target.building);

    const CycleInfo cycle = getCycleInfo(target);
    m_buffers->setBuffers(*target.building, cycle.perCycleInputs, cycle.perCycleOutputs);
    m_production->setProduction(cycle.runsProduction, *target.building,
                                cycle.durationSeconds,
                                getContext().sim->getCurrentTick());
}
