#ifndef LIBTORRENT_LISTEN_H
#define LIBTORRENT_LISTEN_H

#include <cinttypes>
#include <functional>
#include <memory>

#include "torrent/event.h"

namespace torrent {

class Listen : public Event {
public:
  ~Listen() override { close(); }

  const char*         type_name() const override { return "listen"; }

  static bool         open_single(Listen* listen, const sockaddr* bind_address,
                                  uint16_t first, uint16_t last, int backlog, bool block_ipv4in6);

  static bool         open_both(Listen* listen_inet, Listen* listen_inet6,
                                const sockaddr* bind_inet_address, const sockaddr* bind_inet6_address,
                                uint16_t first, uint16_t last, int backlog, bool block_ipv4in6);

  void                close();

  uint16_t            port() const    { return m_port; }

  auto&               slot_accepted() { return m_slot_accepted; }

  void                event_read() override;
  void                event_write() override;
  void                event_error() override;

private:
  using slot_accept_type = std::function<void(std::unique_ptr<Handshake>& handshake, int, const sockaddr*)>;

  void                open_done(int fd, uint16_t port, int backlog);

  uint16_t            m_port{0};
  slot_accept_type    m_slot_accepted;
};

} // namespace torrent

#endif // LIBTORRENT_TORRENT_H
