#ifndef SWIFT_NET_NET_MGR_H
#define SWIFT_NET_NET_MGR_H

#include <swift/data.h>
#include <swift/stdlib.h>

#include <swift/net/api.h>

typedef struct swift_monitor_t swift_monitor_t;
typedef struct swift_sock_t swift_sock_t;

typedef struct swift_net_mgr_t swift_net_mgr_t;
typedef struct swift_net_mgr_ops_t swift_net_mgr_ops_t;
typedef struct swift_peer_t swift_peer_t;

typedef void (* swift_on_peer_connect_fn_t)(swift_net_mgr_t *net_mgr,
	swift_peer_t *peer);
typedef void (* swift_on_peer_disconnect_fn_t)(swift_net_mgr_t *net_mgr,
	swift_peer_t *peer);
typedef void (* swift_on_peer_recv_fn_t)(swift_net_mgr_t *net_mgr,
	swift_peer_t *peer, void *data, size_t size);
typedef void (* swift_on_peer_send_fn_t)(swift_net_mgr_t *net_mgr,
	swift_peer_t *peer, const void *data, size_t size,
	void *user_data);

struct swift_net_mgr_t {
	swift_htable_t *listeners, *peers;
	swift_monitor_t *monitor;
	swift_net_mgr_ops_t *ops;
	void *user_data;
};

struct swift_net_mgr_ops_t {
	swift_on_peer_connect_fn_t on_connect;
	swift_on_peer_disconnect_fn_t on_disconnect;
	swift_on_peer_recv_fn_t on_recv;
	swift_on_peer_send_fn_t on_send;
};

struct swift_peer_t {
	swift_sock_t *sock;
	void *user_data;
	char *data;
	size_t size;
	bool is_connected;
};

SWIFT_NET_API swift_net_mgr_t *swift_new_net_mgr(
	swift_net_mgr_ops_t *ops, unsigned int thread_count,
	void *user_data);
SWIFT_NET_API void swift_del_net_mgr(swift_net_mgr_t *net_mgr);
SWIFT_NET_API bool swift_add_listener(swift_net_mgr_t *net_mgr,
	swift_addr_t *addr);
SWIFT_NET_API size_t swift_add_listeners(swift_net_mgr_t *net_mgr,
	const char *host, uint16_t port);
SWIFT_NET_API size_t swift_peer_hash(const void *data);
SWIFT_NET_API bool swift_peer_eq(const void *lhs_, const void *rhs_);
SWIFT_NET_API swift_peer_t *swift_new_peer_from(
	swift_net_mgr_t *net_mgr, swift_sock_t *sock);
SWIFT_NET_API void swift_del_peer(swift_net_mgr_t *net_mgr,
	swift_peer_t *peer);
SWIFT_NET_API swift_peer_t *swift_get_peer(
	swift_net_mgr_t *net_mgr, swift_sock_t *sock);
SWIFT_NET_API bool swift_add_peer(swift_net_mgr_t *net_mgr,
	swift_addr_t *addr);
SWIFT_NET_API bool swift_add_peers(swift_net_mgr_t *net_mgr,
	const char *host, uint16_t port);
SWIFT_NET_API bool swift_peer_send(swift_net_mgr_t *net_mgr,
	swift_peer_t *peer, const void *data, size_t size,
	void *user_data);
SWIFT_NET_API size_t swift_peer_broadcast(swift_net_mgr_t *net_mgr,
	const void *data, size_t size, void *user_data);
#endif /* SWIFT_NET_NET_MGR_H */
