#pragma once

#include "qsacn_global.h"
#include "qsacnuniverse.h"
#include "sacn/node.h"

#include <QHash>
#include <QHostAddress>
#include <QUdpSocket>
#include <QUuid>


/**
 * @brief The QSacnNode class
 */
class QT_EXPORT QSacnNode
    : public QUdpSocket
    , public sACN::Node
{
    Q_OBJECT

public:
    explicit QSacnNode(QObject *parent = nullptr, QUuid = QUuid::createUuid());
    ~QSacnNode();

    // rlp component
    void rlpSend(const ACN::PDU::Stream, const ACN::SDT::UDP::ipAddress&) override;

    QSacnUniverse* universe(const uint16_t u);
    QSacnUniverse* source(const uint16_t u);

public slots:
    void subscribe(const uint16_t) override;
    void unsubscribe(const uint16_t) override;
    void create(const uint16_t) override;
    void terminate(const uint16_t) override;

signals:
    void discoveryUpdates();
    void subscribing(QSacnUniverse*);
    void unsubscribing(QSacnUniverse*);
    void creating(QSacnUniverse*);
    void terminating(QSacnUniverse*);

private:
    void udpReceive();

    QHash<uint16_t, QSacnUniverse*> rx_universes;
    QHash<uint16_t, QSacnUniverse*> tx_universes;

public:
    /// \cite sACN 9.3.1 Allocation of IPv4 Multicast Addresses
    ///
    /// Multicast addresses are from the IPv4 Local Scope.
    static QHostAddress IPv4MulticastAddress(const uint16_t universe) {
      sACN::ipAddress ip = sACN::IPv4MulticastAddress(universe);
      return QHostAddress(ip.address.ipv4.value);
    };
    /// \cite sACN 9.3.2 Allocation of IPv6 Multicast Addresses
    static QHostAddress IPv6MulticastAddress(const uint16_t universe) {
      sACN::ipAddress ip = sACN::IPv6MulticastAddress(universe);
      return QHostAddress(ip.address.ipv6.bytes);
    };
};

