#pragma once

#include "Message.h"
#include "defs.h"

#include <mutex>
#include <queue>

namespace dBus
{
class Bus;
//--------------------------------------------------------------
class Node
{
  friend class Bus;

  public:
  Node() = delete;                                   // Default constructor
  virtual ~Node();                                   // Default destructor
  Node(const Node &obj)                = delete;     // Copy constructor
  Node(Node &&obj) noexcept            = delete;     // Move constructor
  Node &operator=(const Node &obj)     = delete;     // Copy assignment operator
  Node &operator=(Node &&obj) noexcept = delete;     // Move assignment operator

  explicit Node(Bus &bus);     // Constructor

  // Event subscription management
  void               subscribe(const HashID &eventType);              // Subscribe to a specific message type
  void               unsubscribe(const HashID &eventType);            // Unsubscribe from a specific message type
  void               unsubscribeAll();                                // Unsubscribe from all message types
  [[nodiscard]] bool isSubscribed(const HashID &eventType) const;     // Check if is subscribed to a specific message type

  void syncWaitForMessage();     // Wait for a message to be received

  // Data transmission
  void postMessage(const std::shared_ptr<Message> &message) const;     // Post a message to the bus

  [[nodiscard]] std::chrono::microseconds getMessageMaxAge() const;     // Get the maximum age of messages in the queue
  [[nodiscard]] size_t                    getMessageCount() const;      // Get the number of received messages
  [[nodiscard]] std::shared_ptr<Message>  popNextMessage();             // Get the next message from the queue

  protected:
  virtual void receiveMessageFromBus(std::shared_ptr<Message> message);     // Receive a message from the bus (to be called by the bus when a message is posted)
  void         notifyMessageQueue();                                        // Notify the node of a new message from the bus

  Bus &m_bus;     // Reference to the bus this node is connected to

  std::atomic_bool m_nodeWaitFlag = false;     // Flag to control the node thread loop

  struct
  {
    mutable std::mutex                   mtx;              // Mutex for thread-safe access to the event queue
    std::queue<std::shared_ptr<Message>> messageQueue;     // Queue of received events
  } m_dBusMessages;
};
//--------------------------------------------------------------
}     // namespace dBus
