#pragma once

#include <cstddef>
#include <memory>
#include <sys/mman.h>
#include <sys/resource.h>

struct Connection;

/**
 * mmap-based Connection Registry for tracking active connections.
 *
 * This registry provides a lock-free mechanism for tracking all connections
 * owned by the server, indexed by file descriptor. The design uses mmap to
 * allocate a large virtual address space efficiently, with physical memory
 * allocated on-demand as connections are created.
 *
 */
struct ConnectionRegistry {
public:
  /**
   * Initialize the connection registry.
   * Allocates virtual address space based on RLIMIT_NOFILE.
   *
   * Aborts the process if mmap fails or RLIMIT_NOFILE cannot be read
   */
  ConnectionRegistry();

  /**
   * Destructor ensures proper cleanup of mmap'd memory.
   */
  ~ConnectionRegistry();

  /**
   * Store a connection in the registry, indexed by its file descriptor.
   * Takes ownership of the connection via unique_ptr.
   *
   * @param fd File descriptor (must be valid and < max_fds_)
   * @param connection unique_ptr to the connection (ownership transferred)
   */
  void store(int fd, std::unique_ptr<Connection> connection);

  /**
   * Remove a connection from the registry and transfer ownership to caller.
   * This transfers ownership via unique_ptr move semantics.
   *
   * @param fd File descriptor
   * @return unique_ptr to the connection, or nullptr if not found
   */
  std::unique_ptr<Connection> remove(int fd);

  /**
   * Get the maximum number of file descriptors supported.
   *
   * @return Maximum file descriptor limit
   */
  size_t max_fds() const { return max_fds_; }

  // Non-copyable and non-movable
  ConnectionRegistry(const ConnectionRegistry &) = delete;
  ConnectionRegistry &operator=(const ConnectionRegistry &) = delete;
  ConnectionRegistry(ConnectionRegistry &&) = delete;
  ConnectionRegistry &operator=(ConnectionRegistry &&) = delete;

private:
  std::atomic<Connection *>
      *connections_;    ///< mmap'd array of raw connection pointers. It's
                        ///< thread-safe without since epoll_ctl happens before
                        ///< epoll_wait, but this makes tsan happy /shrug.
  size_t max_fds_;      ///< Maximum file descriptor limit
  size_t aligned_size_; ///< Page-aligned size for munmap
};
