#pragma once

#include <vector>

#include <QPoint>

#include "Port.h"
#include "Rotation.h"

// Geometry of a building's input/output ports. A Port names the tile *outside* the
// building together with the direction items flow across it; these helpers give the
// building body tile on the other side of that edge, which is where the virtual
// input/output belt lives.
//
// Shared by the simulation (which moves items across the edge) and the renderer
// (which draws the virtual belt), so the two cannot disagree about which tile a
// port belongs to.

// The building body tile that owns an output port, given the port's outside tile
// (port.tile) and its facing direction. The virtual output belt occupies this tile
// and flows toward port.tile (REQ-MAT-OUTPUT-EMERGE).
inline QPoint outputBodyTile(QPoint portTile, Rotation direction)
{
    switch (direction)
    {
        case Rotation::East:  return portTile + QPoint(-1,  0);
        case Rotation::West:  return portTile + QPoint( 1,  0);
        case Rotation::North: return portTile + QPoint( 0,  1);
        case Rotation::South: return portTile + QPoint( 0, -1);
    }
    return portTile;
}

// The building body tile an input port feeds into, given the port's outside belt
// tile (port.tile) and its inward flow direction. The virtual input belt occupies
// this tile and flows from the outer edge (progress 0.0) to the centre (0.5)
// (REQ-MAT-INPUT-INTAKE).
inline QPoint inputBodyTile(QPoint portTile, Rotation inwardDirection)
{
    switch (inwardDirection)
    {
        case Rotation::East:  return portTile + QPoint( 1,  0);
        case Rotation::West:  return portTile + QPoint(-1,  0);
        case Rotation::North: return portTile + QPoint( 0, -1);
        case Rotation::South: return portTile + QPoint( 0,  1);
    }
    return portTile;
}

// Every belt-facing edge of a footprint that is not already an output port — the
// tiles a belt can feed the building from, with the direction items must flow to
// enter (REQ-MAT-INPUT-PORTS, REQ-BLD-BELT-DRAG). bodyCells and outputPorts are
// in absolute tile coordinates, and so is the result.
std::vector<Port> computeInputPorts(const std::vector<QPoint>& bodyCells,
                                    const std::vector<Port>& outputPorts);
