#ifndef DATA_LINK_HPP_
#define DATA_LINK_HPP_

#include <vector>
#include <memory>
#include <Serialize/Serialize.hpp>
#include <WorldComponent/Wiring/Wiring.hpp>
#include <Machine/Machine.hpp>
#include <Side/Side.hpp>
#include <Utilities/Flags.hpp>

/**
 * @brief Represents a link between a machine port and other ports.
 */
class DataLink
{
private:
    struct Endpoint
    {
        std::weak_ptr<Machine> machine;
        Side side;
    };

    std::vector<Endpoint> endpoints;

public:
    enum class Channel
    {
        Red = 0,
        Green = 1,
        Blue = 2,
        Magenta = 3,
    };

    typedef Flags<DataLink::Channel, uint8_t> ChannelBitmap;

    static std::shared_ptr<DataLink> dummyLink;
    const glm::ivec3 pos = glm::ivec3(0, 0, 0);
    const Side side = Side(0);

    DataLink() = default;

    /**
     * @brief Construct a new data link from the specified data.
     */
    DataLink(LocalWorld &world, std::shared_ptr<WorldGridNode> node, std::vector<Wiring::Port> &ports, size_t startingPort);

    /**
     * @brief Get the data link from the specified machine's side.
     * 
     * @param machine The machine requesting a link.
     * @param side The side of the machine where we are searching from.
     */
    static std::shared_ptr<DataLink> get(Machine &machine, Side side);

    /**
     * @brief OR outputs from the machines connected to this link, with the existing ones.
     */
    void combineStates(ChannelBitmap &bitmap);
};

DERIVE_STATIC_CAST_SERIALIZER(DataLink::Channel, uint8_t);

#endif