#include "ConstructionSystem.h"

#include "BuildingBuffers.h"
#include "BuildingType.h"
#include "FactoryQueries.h"
#include "PortGeometry.h"
#include "SurfaceMask.h"
#include "tracing.h"

void ConstructionSystem::tick(FactoryState& state, BeltSystem& belts, Tick currentTick)
{
	TRACE();
    if (state.constructionQueue.empty())
    {
        return;
    }

    ConstructionSite& front = state.constructionQueue.front();

    // Guard: if somehow the front site was never started, start it now.
    if (front.completesAt == 0)
    {
        const BuildingDef* def = m_config.buildings.findBuildingDef(front.type);
        if (def)
        {
            front.completesAt = currentTick + secondsToTicks(def->constructionTimeSeconds);
        }
        return;
    }

    if (currentTick < front.completesAt)
    {
        return;
    }

    // Promote construction site to an operational Building.
    const BuildingDef* def = m_config.buildings.findBuildingDef(front.type);
    const ParsedSurfaceMask mask = parseSurfaceMask(
        def ? def->surfaceMask : std::vector<std::string>{},
        front.rotation);

    Building building;
    building.id        = front.id;
    building.anchor    = front.anchor;
    building.footprint = front.footprint;
    building.rotation  = front.rotation;
    building.type      = front.type;
    building.recipeId  = front.recipeId;
    building.shipLayout = front.shipLayout;

    for (const QPoint& cell : mask.bodyCells)
    {
        building.bodyCells.push_back(front.anchor + cell);
    }
    for (const Port& port : mask.outputPorts)
    {
        Port absPort;
        absPort.tile      = front.anchor + port.tile;
        absPort.direction = port.direction;
        building.outputPorts.push_back(absPort);
    }
    building.emergingItems.resize(building.outputPorts.size());
    building.inputPorts = computeInputPorts(building.bodyCells, building.outputPorts);
    building.incomingItems.assign(building.inputPorts.size(), {});

    if (building.type == BuildingType::SalvageBay)
    {
        initSalvageBayBuffer(m_config, building);
    }
    else if (!building.recipeId.empty())
    {
        if (building.type == BuildingType::Shipyard)
        {
            initShipyardBuffers(m_config, building);
        }
        else
        {
            const RecipeDef* recipe = m_config.recipes.findRecipeDef(building.recipeId, building.type);
            if (recipe)
            {
                initBuffers(building, *recipe);
            }
        }
    }

    // Register with BeltSystem before the move (mask/building stays valid). Any
    // filters configured while under construction carry over (REQ-BLD-SITE-CONFIG).
    reregisterBeltTile(belts, m_config, building, front.splitterFilterA, front.splitterFilterB);

    state.buildings.push_back(std::move(building));

    state.constructionQueue.pop_front();

    // Start next queued site if present.
    if (!state.constructionQueue.empty() && state.constructionQueue.front().completesAt == 0)
    {
        const BuildingDef* nextDef =
            m_config.buildings.findBuildingDef(state.constructionQueue.front().type);
        if (nextDef)
        {
            state.constructionQueue.front().completesAt =
                currentTick + secondsToTicks(nextDef->constructionTimeSeconds);
        }
    }
}

