#include "PortGeometry.h"

#include <set>
#include <utility>

std::vector<Port> computeInputPorts(
    const std::vector<QPoint>& bodyCells,
    const std::vector<Port>& outputPorts)
{
    // Build lookup sets for quick membership checks.
    std::set<std::pair<int, int>> bodySet;
    for (const QPoint& cell : bodyCells)
    {
        bodySet.insert({cell.x(), cell.y()});
    }

    std::set<std::pair<int, int>> outputPortTiles;
    for (const Port& port : outputPorts)
    {
        outputPortTiles.insert({port.tile.x(), port.tile.y()});
    }

    // Neighbour deltas and the corresponding "inward" belt direction.
    const int dx[4]            = {-1,  1,  0,  0};
    const int dy[4]            = { 0,  0, -1,  1};
    const Rotation inward[4]   = {
        Rotation::East,   // neighbour is to the West; belt flows East toward building
        Rotation::West,   // neighbour is to the East; belt flows West toward building
        Rotation::South,  // neighbour is above (row-1); belt flows South toward building
        Rotation::North   // neighbour is below (row+1); belt flows North toward building
    };

    std::set<std::pair<int, int>> seen;
    std::vector<Port> inputPorts;

    for (const QPoint& cell : bodyCells)
    {
        for (int i = 0; i < 4; ++i)
        {
            const int nx = cell.x() + dx[i];
            const int ny = cell.y() + dy[i];
            const std::pair<int, int> neighbor = {nx, ny};

            if (bodySet.count(neighbor))       { continue; }
            if (outputPortTiles.count(neighbor)){ continue; }
            if (seen.count(neighbor))           { continue; }

            seen.insert(neighbor);
            Port port;
            port.tile      = QPoint(nx, ny);
            port.direction = inward[i];
            inputPorts.push_back(port);
        }
    }

    return inputPorts;
}
