#ifndef SWIFT_NET_SOCK_H
#define SWIFT_NET_SOCK_H

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

#include <swift/net/api.h>
#include <swift/net/addr.h>

typedef struct swift_monitor_t swift_monitor_t;
typedef struct swift_sock_t swift_sock_t;

typedef void (* swift_on_accept_fn_t)(bool success, swift_sock_t *sock,
	swift_sock_t *peer, void *user_data);
typedef void (* swift_on_connect_fn_t)(bool success, swift_sock_t *sock,
	void *user_data);
typedef void (* swift_on_recv_fn_t)(bool success, swift_sock_t *sock,
	void *data, size_t size, void *user_data);
typedef void (* swift_on_send_fn_t)(bool success, swift_sock_t *sock,
	const void *data, size_t size, void *user_data);

#define SWIFT_FOREIGN_SOCK (1 << 0)

#define SWIFT_SOCK_WAIT (1 << 0)

enum swift_proto_t {
	SWIFT_PROTO_UDP,
	SWIFT_PROTO_TCP,
};

struct swift_sock_t {
	swift_ref_t ref;
	void *data;
	swift_monitor_t *monitor;
	unsigned int flags, addr_type, proto_type;
};

SWIFT_NET_API bool swift_init_sock(swift_sock_t *sock,
	unsigned int addr_type, unsigned int proto_type);
SWIFT_NET_API bool swift_init_sock_from(swift_sock_t *sock,
	unsigned int addr_type, unsigned int proto_type, const void *data);
SWIFT_NET_API void swift_term_sock(swift_sock_t *sock);
SWIFT_NET_API swift_sock_t *swift_new_sock(unsigned int addr_type,
	unsigned int proto_type);
SWIFT_NET_API swift_sock_t *swift_new_sock_from(unsigned int addr_type,
	unsigned int proto_type, const void *data);
SWIFT_NET_API size_t swift_sock_hash(const void *data);
SWIFT_NET_API bool swift_sock_eq(const void *lhs, const void *rhs);
SWIFT_NET_API size_t swift_peer_sock_hash(const void *data);
SWIFT_NET_API bool swift_peer_sock_eq(const void *lhs, const void *rhs);
SWIFT_NET_API void swift_del_sock(swift_sock_t *sock);
SWIFT_NET_API swift_sock_t *swift_ref_sock(swift_sock_t *sock);
SWIFT_NET_API unsigned int swift_sock_get_flags(swift_sock_t *sock);
SWIFT_NET_API bool swift_sock_set_flags(swift_sock_t *sock,
	unsigned int flags);
SWIFT_NET_API swift_addr_t *swift_sock_local_addr(
	swift_sock_t *sock);
SWIFT_NET_API swift_addr_t *swift_sock_remote_addr(
	swift_sock_t *sock);
SWIFT_NET_API bool swift_sock_connect(swift_sock_t *sock,
	swift_addr_t *addr);
SWIFT_NET_API bool swift_queue_connect(swift_sock_t *sock,
	swift_addr_t *addr, swift_on_connect_fn_t on_connect,
	void *user_data);
SWIFT_NET_API bool swift_sock_bind(swift_sock_t *sock,
	swift_addr_t *addr);
SWIFT_NET_API bool swift_sock_bind_name(swift_sock_t *sock,
	const char *name, uint16_t port);
SWIFT_NET_API bool swift_sock_listen(swift_sock_t *sock,
	unsigned int back_log);
SWIFT_NET_API swift_sock_t *swift_sock_accept(swift_sock_t *sock);
SWIFT_NET_API bool swift_queue_accept(swift_sock_t *sock,
	swift_on_accept_fn_t on_accept, void *user_data);
SWIFT_NET_API size_t swift_sock_recv(swift_sock_t *sock, void *data,
	size_t size);
SWIFT_NET_API bool swift_queue_recv(swift_sock_t *sock, void *data,
	size_t size, swift_on_recv_fn_t on_recv, void *user_data);
SWIFT_NET_API size_t swift_sock_send(swift_sock_t *sock,
	const void *data, size_t size);
SWIFT_NET_API bool swift_queue_send(swift_sock_t *sock,
	const void *data, size_t size, swift_on_send_fn_t on_send,
	void *user_data);

#endif /* SWIFT_NET_SOCK_H */
