#pragma once

#include "Emu/Memory/vm_ptr.h"

// Return Codes
constexpr auto CELL_RUDP_SUCCESS = CELL_OK;

enum CellRudpError : u32
{
	CELL_RUDP_ERROR_NOT_INITIALIZED = 0x80770001,
	CELL_RUDP_ERROR_ALREADY_INITIALIZED = 0x80770002,
	CELL_RUDP_ERROR_INVALID_CONTEXT_ID = 0x80770003,
	CELL_RUDP_ERROR_INVALID_ARGUMENT = 0x80770004,
	CELL_RUDP_ERROR_INVALID_OPTION = 0x80770005,
	CELL_RUDP_ERROR_INVALID_MUXMODE = 0x80770006,
	CELL_RUDP_ERROR_MEMORY = 0x80770007,
	CELL_RUDP_ERROR_INTERNAL = 0x80770008,
	CELL_RUDP_ERROR_CONN_RESET = 0x80770009,
	CELL_RUDP_ERROR_CONN_REFUSED = 0x8077000a,
	CELL_RUDP_ERROR_CONN_TIMEOUT = 0x8077000b,
	CELL_RUDP_ERROR_CONN_VERSION_MISMATCH = 0x8077000c,
	CELL_RUDP_ERROR_CONN_TRANSPORT_TYPE_MISMATCH = 0x8077000d,
	CELL_RUDP_ERROR_QUALITY_LEVEL_MISMATCH = 0x8077000e,
	CELL_RUDP_ERROR_THREAD = 0x8077000f,
	CELL_RUDP_ERROR_THREAD_IN_USE = 0x80770010,
	CELL_RUDP_ERROR_NOT_ACCEPTABLE = 0x80770011,
	CELL_RUDP_ERROR_MSG_TOO_LARGE = 0x80770012,
	CELL_RUDP_ERROR_NOT_BOUND = 0x80770013,
	CELL_RUDP_ERROR_CANCELLED = 0x80770014,
	CELL_RUDP_ERROR_INVALID_VPORT = 0x80770015,
	CELL_RUDP_ERROR_WOULDBLOCK = 0x80770016,
	CELL_RUDP_ERROR_VPORT_IN_USE = 0x80770017,
	CELL_RUDP_ERROR_VPORT_EXHAUSTED = 0x80770018,
	CELL_RUDP_ERROR_INVALID_SOCKET = 0x80770019,
	CELL_RUDP_ERROR_BUFFER_TOO_SMALL = 0x8077001a,
	CELL_RUDP_ERROR_MSG_MALFORMED = 0x8077001b,
	CELL_RUDP_ERROR_ADDR_IN_USE = 0x8077001c,
	CELL_RUDP_ERROR_ALREADY_BOUND = 0x8077001d,
	CELL_RUDP_ERROR_ALREADY_EXISTS = 0x8077001e,
	CELL_RUDP_ERROR_INVALID_POLL_ID = 0x8077001f,
	CELL_RUDP_ERROR_TOO_MANY_CONTEXTS = 0x80770020,
	CELL_RUDP_ERROR_IN_PROGRESS = 0x80770021,
	CELL_RUDP_ERROR_NO_EVENT_HANDLER = 0x80770022,
	CELL_RUDP_ERROR_PAYLOAD_TOO_LARGE = 0x80770023,
	CELL_RUDP_ERROR_END_OF_DATA = 0x80770024,
	CELL_RUDP_ERROR_ALREADY_ESTABLISHED = 0x80770025,
	CELL_RUDP_ERROR_KEEP_ALIVE_FAILURE = 0x80770026,
};

// Context options
enum
{
	CELL_RUDP_OPTION_MAX_PAYLOAD = 1,
	CELL_RUDP_OPTION_SNDBUF = 2,
	CELL_RUDP_OPTION_RCVBUF = 3,
	CELL_RUDP_OPTION_NODELAY = 4,
	CELL_RUDP_OPTION_DELIVERY_CRITICAL = 5,
	CELL_RUDP_OPTION_ORDER_CRITICAL = 6,
	CELL_RUDP_OPTION_NONBLOCK = 7,
	CELL_RUDP_OPTION_STREAM = 8,
	CELL_RUDP_OPTION_CONNECTION_TIMEOUT = 9,
	CELL_RUDP_OPTION_CLOSE_WAIT_TIMEOUT = 10,
	CELL_RUDP_OPTION_AGGREGATION_TIMEOUT = 11,
	CELL_RUDP_OPTION_LAST_ERROR = 14,
	CELL_RUDP_OPTION_READ_TIMEOUT = 15,
	CELL_RUDP_OPTION_WRITE_TIMEOUT = 16,
	CELL_RUDP_OPTION_FLUSH_TIMEOUT = 17,
	CELL_RUDP_OPTION_KEEP_ALIVE_INTERVAL = 18,
	CELL_RUDP_OPTION_KEEP_ALIVE_TIMEOUT = 19,
};

// Polling event flags
enum
{
	CELL_RUDP_POLL_EV_READ = 0x0001,
	CELL_RUDP_POLL_EV_WRITE = 0x0002,
	CELL_RUDP_POLL_EV_FLUSH = 0x0004,
	CELL_RUDP_POLL_EV_ERROR = 0x0008,
};

struct sys_net_sockaddr;

using CellRudpEventHandler = s32(s32 event_id, s32 soc, vm::cptr<u8> data, u32 datalen, vm::cptr<sys_net_sockaddr> addr, u32 addrlen, vm::ptr<void> arg);

using CellRudpAllocatorFuncAlloc = vm::ptr<void>(u32 size);
using CellRudpAllocatorFuncFree = void(vm::ptr<void> ptr);

struct CellRudpAllocator
{
	vm::bptr<CellRudpAllocatorFuncAlloc> app_malloc;
	vm::bptr<CellRudpAllocatorFuncFree> app_free;
};
