#ifndef _LIB_BARRELFISH_UMP_NET_CLIENT_H
#define _LIB_BARRELFISH_UMP_NET_CLIENT_H

#include <aos/aos.h>
#include <aos/ump_chan.h>
#include <aos/ump_net.h>

// This is the client library for the UMP net server.

/**
 * @brief Initialize networking in this process.
 *
 * @param ws waitset on which networking runs
 */
errval_t ump_net_init (struct waitset *ws);

/**
 * @brief Internal data structure. You need to allocate this space when
 * making a call, and can release it in the callback.
 */
struct ump_net_call {
    struct ump_send_queue_entry ump_entry;
    struct ump_net_out_header out_header;
    struct ump_net_in_header in_header;
    bool half_done;
    void *cb;
    void *cb_arg;
    struct ump_net_call *next;
};

typedef void (*ump_net_udp_send_callback_t)(void *arg, errval_t err);
/**
 * @brief Send an UDP packet.
 * @param call You need to allocate this space until cb is called.
 * @param cb This will be called when the operation is complete, with cb_arg and an error value.
 */
void ump_net_udp_send(
    struct ump_net_call *call,
    uint32_t dest_ip,
    uint16_t src_port,
    uint16_t dest_port,
    size_t payload_size, const void *payload,
    ump_net_udp_send_callback_t cb, void *cb_arg
);

typedef void (*ump_net_udp_recv_handler_t)(void *arg, struct ump_net_ev_udp_recv *udp_recv, size_t payload_size);
typedef void (*ump_net_udp_listen_callback_t)(void *arg, errval_t err, uint16_t dest_port);
/**
 * @brief Listen for UDP packets.
 * @param call You need to allocate this space until cb is called.
 * @param dest_port UDP port to listen on. If 0, an ephemeral port is allocated, and passed to the callback.
 * @param recv_handler This will be called when a packet arrives.
 * When the callback is called, you *must* call ump_net_recv_payload.
 * @param cb This will be called when the operation is complete, with cb_arg, an error value, and the port.
 */
void ump_net_udp_listen (
    struct ump_net_call *call,
    uint16_t dest_port,
    ump_net_udp_recv_handler_t recv_handler, void *recv_handler_arg,
    ump_net_udp_listen_callback_t cb, void *cb_arg
);

typedef void (*ump_net_udp_listen_stop_callback_t)(void *arg, errval_t err);
/**
 * @brief Stop listening for UDP packets.
 * @param call You need to allocate this space until cb is called.
 * @param cb This will be called when the operation is complete, with cb_arg and an error value.
 */
void ump_net_udp_listen_stop (
    struct ump_net_call *call,
    uint16_t dest_port,
    ump_net_udp_listen_stop_callback_t cb, void *cb_arg
);
/**
 * @brief Receive payload.
 * @param payload Buffer to write data into.
 * Must have size payload_size (argument of recv_handler).
 * Can be NULL to drop the payload.
 * @param callback Will be called when all data has been received.
 * Can be NULL when payload is NULL.
 */
void ump_net_recv_payload (
    void *payload,
    ump_recv_payload_callback_fn_t callback, void *callback_arg
);

#endif // _LIB_BARRELFISH_UMP_NET_CLIENT_H
