/*
 * Copyright (c) 2023 Nordic Semiconductor ASA
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <string.h>
#include <zephyr/logging/log.h>
LOG_MODULE_DECLARE(net_coap, CONFIG_COAP_LOG_LEVEL);

#include <zephyr/net/socket.h>

#include <zephyr/net/coap.h>
#include <zephyr/net/coap_client.h>

#define COAP_VERSION 1
#define COAP_SEPARATE_TIMEOUT 6000
#define COAP_PERIODIC_TIMEOUT 500
#define BLOCK1_OPTION_SIZE 4
#define PAYLOAD_MARKER_SIZE 1

static struct coap_client *clients[CONFIG_COAP_CLIENT_MAX_INSTANCES];
static int num_clients;
static K_SEM_DEFINE(coap_client_recv_sem, 0, 1);
static atomic_t coap_client_recv_active;

static int send_request(int sock, const void *buf, size_t len, int flags,
			const struct sockaddr *dest_addr, socklen_t addrlen)
{
	if (addrlen == 0) {
		return zsock_sendto(sock, buf, len, flags, NULL, 0);
	} else {
		return zsock_sendto(sock, buf, len, flags, dest_addr, addrlen);
	}
}

static int receive(int sock, void *buf, size_t max_len, int flags,
		   struct sockaddr *src_addr, socklen_t *addrlen)
{
	if (*addrlen == 0) {
		return zsock_recvfrom(sock, buf, max_len, flags, NULL, NULL);
	} else {
		return zsock_recvfrom(sock, buf, max_len, flags, src_addr, addrlen);
	}
}

static void reset_block_contexts(struct coap_client_internal_request *request)
{
	request->recv_blk_ctx.block_size = 0;
	request->recv_blk_ctx.total_size = 0;
	request->recv_blk_ctx.current = 0;

	request->send_blk_ctx.block_size = 0;
	request->send_blk_ctx.total_size = 0;
	request->send_blk_ctx.current = 0;
}

static void reset_internal_request(struct coap_client_internal_request *request)
{
	request->offset = 0;
	request->last_id = 0;
	reset_block_contexts(request);
}

static int coap_client_schedule_poll(struct coap_client *client, int sock,
				     struct coap_client_request *req,
				     struct coap_client_internal_request *internal_req)
{
	client->fd = sock;
	memcpy(&internal_req->coap_request, req, sizeof(struct coap_client_request));
	internal_req->request_ongoing = true;

	if (!coap_client_recv_active) {
		k_sem_give(&coap_client_recv_sem);
	}
	atomic_set(&coap_client_recv_active, 1);

	return 0;
}

bool has_ongoing_request(struct coap_client *client)
{
	for (int i = 0; i < CONFIG_COAP_CLIENT_MAX_REQUESTS; i++) {
		if (client->requests[i].request_ongoing == true) {
			return true;
		}
	}

	return false;
}

struct coap_client_internal_request *get_free_request(struct coap_client *client)
{
	for (int i = 0; i < CONFIG_COAP_CLIENT_MAX_REQUESTS; i++) {
		if (client->requests[i].request_ongoing == false) {
			return &client->requests[i];
		}
	}

	return NULL;
}

static bool has_ongoing_requests(void)
{
	bool has_requests = false;

	for (int i = 0; i < num_clients; i++) {
		has_requests |= has_ongoing_request(clients[i]);
	}

	return has_requests;
}

static enum coap_block_size coap_client_default_block_size(void)
{
	switch (CONFIG_COAP_CLIENT_BLOCK_SIZE) {
	case 16:
		return COAP_BLOCK_16;
	case 32:
		return COAP_BLOCK_32;
	case 64:
		return COAP_BLOCK_64;
	case 128:
		return COAP_BLOCK_128;
	case 256:
		return COAP_BLOCK_256;
	case 512:
		return COAP_BLOCK_512;
	case 1024:
		return COAP_BLOCK_1024;
	}

	return COAP_BLOCK_256;
}

static int coap_client_init_request(struct coap_client *client,
				    struct coap_client_request *req,
				    struct coap_client_internal_request *internal_req,
				    bool reconstruct)
{
	int ret = 0;
	int i;

	memset(client->send_buf, 0, sizeof(client->send_buf));

	if (!reconstruct) {
		uint8_t *token = coap_next_token();

		internal_req->last_id = coap_next_id();
		internal_req->request_tkl = COAP_TOKEN_MAX_LEN & 0xf;
		memcpy(internal_req->request_token, token, internal_req->request_tkl);
	}

	ret = coap_packet_init(&internal_req->request, client->send_buf, MAX_COAP_MSG_LEN,
			       1, req->confirmable ? COAP_TYPE_CON : COAP_TYPE_NON_CON,
			       COAP_TOKEN_MAX_LEN, internal_req->request_token, req->method,
			       internal_req->last_id);

	if (ret < 0) {
		LOG_ERR("Failed to init CoAP message %d", ret);
		goto out;
	}

	ret = coap_packet_set_path(&internal_req->request, req->path);

	if (ret < 0) {
		LOG_ERR("Failed to parse path to options %d", ret);
		goto out;
	}

	/* Add content format option only if there is a payload */
	if (req->payload) {
		ret = coap_append_option_int(&internal_req->request,
					     COAP_OPTION_CONTENT_FORMAT, req->fmt);

		if (ret < 0) {
			LOG_ERR("Failed to append content format option");
			goto out;
		}
	}

	/* Blockwise receive ongoing, request next block. */
	if (internal_req->recv_blk_ctx.current > 0) {
		ret = coap_append_block2_option(&internal_req->request,
						&internal_req->recv_blk_ctx);

		if (ret < 0) {
			LOG_ERR("Failed to append block 2 option");
			goto out;
		}
	}

	/* Add extra options if any */
	for (i = 0; i < req->num_options; i++) {
		ret = coap_packet_append_option(&internal_req->request, req->options[i].code,
						req->options[i].value, req->options[i].len);

		if (ret < 0) {
			LOG_ERR("Failed to append %d option", req->options[i].code);
			goto out;
		}
	}

	if (req->payload) {
		uint16_t payload_len;
		uint16_t offset;

		/* Blockwise send ongoing, add block1 */
		if (internal_req->send_blk_ctx.total_size > 0 ||
		   (req->len > CONFIG_COAP_CLIENT_MESSAGE_SIZE)) {

			if (internal_req->send_blk_ctx.total_size == 0) {
				coap_block_transfer_init(&internal_req->send_blk_ctx,
							 coap_client_default_block_size(),
							 req->len);
				/* Generate request tag */
				uint8_t *tag = coap_next_token();

				memcpy(internal_req->request_tag, tag, COAP_TOKEN_MAX_LEN);
			}
			ret = coap_append_block1_option(&internal_req->request,
							&internal_req->send_blk_ctx);

			if (ret < 0) {
				LOG_ERR("Failed to append block1 option");
				goto out;
			}

			ret = coap_packet_append_option(&internal_req->request,
				COAP_OPTION_REQUEST_TAG, internal_req->request_tag,
				COAP_TOKEN_MAX_LEN);

			if (ret < 0) {
				LOG_ERR("Failed to append request tag option");
				goto out;
			}
		}

		ret = coap_packet_append_payload_marker(&internal_req->request);

		if (ret < 0) {
			LOG_ERR("Failed to append payload marker to CoAP message");
			goto out;
		}

		if (internal_req->send_blk_ctx.total_size > 0) {
			uint16_t block_in_bytes =
				coap_block_size_to_bytes(internal_req->send_blk_ctx.block_size);

			payload_len = internal_req->send_blk_ctx.total_size -
				      internal_req->send_blk_ctx.current;
			if (payload_len > block_in_bytes) {
				payload_len = block_in_bytes;
			}
			offset = internal_req->send_blk_ctx.current;
		} else {
			payload_len = req->len;
			offset = 0;
		}

		ret = coap_packet_append_payload(&internal_req->request, req->payload + offset,
						 payload_len);

		if (ret < 0) {
			LOG_ERR("Failed to append payload to CoAP message");
			goto out;
		}

		if (internal_req->send_blk_ctx.total_size > 0) {
			coap_next_block(&internal_req->request, &internal_req->send_blk_ctx);
		}
	}
out:
	return ret;
}

int coap_client_req(struct coap_client *client, int sock, const struct sockaddr *addr,
		    struct coap_client_request *req, struct coap_transmission_parameters *params)
{
	int ret;

	struct coap_client_internal_request *internal_req = get_free_request(client);

	if (internal_req == NULL) {
		return -EAGAIN;
	}

	if (sock < 0 || req == NULL || req->path == NULL) {
		return -EINVAL;
	}

	/* Don't allow changing to a different socket if there is already request ongoing. */
	if (client->fd != sock && has_ongoing_request(client)) {
		return -EALREADY;
	}

	/* Don't allow changing to a different address if there is already request ongoing. */
	if (addr != NULL) {
		if (memcmp(&client->address, addr, sizeof(*addr)) != 0) {
			if (has_ongoing_request(client)) {
				LOG_WRN("Can't change to a different socket, request ongoing.");
				return -EALREADY;
			}

			memcpy(&client->address, addr, sizeof(*addr));
			client->socklen = sizeof(client->address);
		}
	} else {
		if (client->socklen != 0) {
			if (has_ongoing_request(client)) {
				LOG_WRN("Can't change to a different socket, request ongoing.");
				return -EALREADY;
			}

			memset(&client->address, 0, sizeof(client->address));
			client->socklen = 0;
		}
	}

	reset_internal_request(internal_req);

	if (k_mutex_lock(&client->send_mutex, K_NO_WAIT)) {
		return -EAGAIN;
	}

	ret = coap_client_init_request(client, req, internal_req, false);
	if (ret < 0) {
		LOG_ERR("Failed to initialize coap request");
		k_mutex_unlock(&client->send_mutex);
		goto out;
	}

	if (client->send_echo) {
		ret = coap_packet_append_option(&internal_req->request, COAP_OPTION_ECHO,
						client->echo_option.value, client->echo_option.len);
		if (ret < 0) {
			LOG_ERR("Failed to append echo option");
			k_mutex_unlock(&client->send_mutex);
			goto out;
		}
		client->send_echo = false;
	}

	ret = coap_client_schedule_poll(client, sock, req, internal_req);
	if (ret < 0) {
		LOG_ERR("Failed to schedule polling");
		k_mutex_unlock(&client->send_mutex);
		goto out;
	}

	/* only TYPE_CON messages need pending tracking */
	if (coap_header_get_type(&internal_req->request) == COAP_TYPE_CON) {
		ret = coap_pending_init(&internal_req->pending, &internal_req->request,
					&client->address, params);

		if (ret < 0) {
			LOG_ERR("Failed to initialize pending struct");
			k_mutex_unlock(&client->send_mutex);
			goto out;
		}

		coap_pending_cycle(&internal_req->pending);
	}

	ret = send_request(sock, internal_req->request.data, internal_req->request.offset, 0,
			  &client->address, client->socklen);

	k_mutex_unlock(&client->send_mutex);

	if (ret < 0) {
		LOG_ERR("Transmission failed: %d", errno);
	} else {
		/* Do not return the number of bytes sent */
		ret = 0;
	}
out:
	return ret;
}

static void report_callback_error(struct coap_client_internal_request *internal_req, int error_code)
{
	if (internal_req->coap_request.cb) {
		internal_req->coap_request.cb(error_code, 0, NULL, 0, true,
					      internal_req->coap_request.user_data);
	}
}

static bool timeout_expired(struct coap_client_internal_request *internal_req)
{
	if (internal_req->pending.timeout == 0) {
		return false;
	}

	return (internal_req->request_ongoing &&
		internal_req->pending.timeout <= (k_uptime_get() - internal_req->pending.t0));
}

static int resend_request(struct coap_client *client,
			  struct coap_client_internal_request *internal_req)
{
	int ret = 0;

	if (internal_req->pending.timeout != 0 && coap_pending_cycle(&internal_req->pending)) {
		LOG_ERR("Timeout in poll, retrying send");

		/* Reset send block context as it was updated in previous init from packet */
		if (internal_req->send_blk_ctx.total_size > 0) {
			internal_req->send_blk_ctx.current = internal_req->offset;
		}
		k_mutex_lock(&client->send_mutex, K_FOREVER);
		ret = coap_client_init_request(client, &internal_req->coap_request,
					       internal_req, true);
		if (ret < 0) {
			LOG_ERR("Error re-creating CoAP request");
		} else {
			ret = send_request(client->fd, internal_req->request.data,
					   internal_req->request.offset, 0, &client->address,
					   client->socklen);
			if (ret > 0) {
				ret = 0;
			} else {
				LOG_ERR("Failed to resend request, %d", ret);
			}
		}
		k_mutex_unlock(&client->send_mutex);
	} else {
		LOG_ERR("Timeout in poll, no more retries left");
		ret = -ETIMEDOUT;
		report_callback_error(internal_req, ret);
		internal_req->request_ongoing = false;
	}

	return ret;
}

static int coap_client_resend_handler(void)
{
	int ret = 0;

	for (int i = 0; i < num_clients; i++) {
		for (int j = 0; j < CONFIG_COAP_CLIENT_MAX_REQUESTS; j++) {
			if (timeout_expired(&clients[i]->requests[j])) {
				ret = resend_request(clients[i], &clients[i]->requests[j]);
			}
		}
	}

	return ret;
}

static int handle_poll(void)
{
	int ret = 0;

	while (1) {
		struct zsock_pollfd fds[CONFIG_COAP_CLIENT_MAX_INSTANCES] = {0};
		int nfds = 0;

		/* Use periodic timeouts */
		for (int i = 0; i < num_clients; i++) {
			fds[i].fd = clients[i]->fd;
			fds[i].events = ZSOCK_POLLIN;
			fds[i].revents = 0;
			nfds++;
		}

		ret = zsock_poll(fds, nfds, COAP_PERIODIC_TIMEOUT);

		if (ret < 0) {
			LOG_ERR("Error in poll:%d", errno);
			errno = 0;
			return ret;
		} else if (ret == 0) {
			/* Resend all the expired pending messages */
			ret = coap_client_resend_handler();

			if (ret < 0) {
				LOG_ERR("Error resending request: %d", ret);
			}

			if (!has_ongoing_requests()) {
				return ret;
			}

		} else {
			for (int i = 0; i < nfds; i++) {
				if (fds[i].revents & ZSOCK_POLLERR) {
					LOG_ERR("Error in poll for socket %d", fds[i].fd);
				}
				if (fds[i].revents & ZSOCK_POLLHUP) {
					LOG_ERR("Error in poll: POLLHUP for socket %d", fds[i].fd);
				}
				if (fds[i].revents & ZSOCK_POLLNVAL) {
					LOG_ERR("Error in poll: POLLNVAL - fd %d not open",
						fds[i].fd);
				}
				if (fds[i].revents & ZSOCK_POLLIN) {
					clients[i]->response_ready = true;
				}
			}

			return 0;
		}
	}

	return ret;
}

static bool token_compare(struct coap_client_internal_request *internal_req,
			  const struct coap_packet *resp)
{
	uint8_t response_token[COAP_TOKEN_MAX_LEN];
	uint8_t response_tkl;

	response_tkl = coap_header_get_token(resp, response_token);

	if (internal_req->request_tkl != response_tkl) {
		return false;
	}

	return memcmp(&internal_req->request_token, &response_token, response_tkl) == 0;
}

static int recv_response(struct coap_client *client, struct coap_packet *response)
{
	int len;
	int ret;

	memset(client->recv_buf, 0, sizeof(client->recv_buf));
	len = receive(client->fd, client->recv_buf, sizeof(client->recv_buf), ZSOCK_MSG_DONTWAIT,
		      &client->address, &client->socklen);

	if (len < 0) {
		LOG_ERR("Error reading response: %d", errno);
		return -EINVAL;
	} else if (len == 0) {
		LOG_ERR("Zero length recv");
		return -EINVAL;
	}

	LOG_DBG("Received %d bytes", len);

	ret = coap_packet_parse(response, client->recv_buf, len, NULL, 0);
	if (ret < 0) {
		LOG_ERR("Invalid data received");
		return ret;
	}

	return ret;
}

static int send_ack(struct coap_client *client, const struct coap_packet *req,
		    uint8_t response_code)
{
	int ret;
	struct coap_packet ack;

	ret = coap_ack_init(&ack, req, client->send_buf, MAX_COAP_MSG_LEN, response_code);
	if (ret < 0) {
		LOG_ERR("Failed to initialize CoAP ACK-message");
		return ret;
	}

	ret = send_request(client->fd, ack.data, ack.offset, 0, &client->address, client->socklen);
	if (ret < 0) {
		LOG_ERR("Error sending a CoAP ACK-message");
		return ret;
	}

	return 0;
}

struct coap_client_internal_request *get_request_with_id(struct coap_client *client,
							 uint16_t message_id)
{
	for (int i = 0; i < CONFIG_COAP_CLIENT_MAX_REQUESTS; i++) {
		if (client->requests[i].request_ongoing == true &&
		    client->requests[i].pending.id == message_id) {
			return &client->requests[i];
		}
	}

	return NULL;
}

struct coap_client_internal_request *get_request_with_token(struct coap_client *client,
							    const struct coap_packet *resp)
{

	uint8_t response_token[COAP_TOKEN_MAX_LEN];
	uint8_t response_tkl;

	response_tkl = coap_header_get_token(resp, response_token);

	for (int i = 0; i < CONFIG_COAP_CLIENT_MAX_REQUESTS; i++) {
		if (client->requests[i].request_ongoing) {
			if (client->requests[i].request_tkl != response_tkl) {
				continue;
			}
			if (memcmp(&client->requests[i].request_token, &response_token,
			    response_tkl) == 0) {
				return &client->requests[i];
			}
		}
	}

	return NULL;
}

static bool find_echo_option(const struct coap_packet *response, struct coap_option *option)
{
	return coap_find_options(response, COAP_OPTION_ECHO, option, 1);
}

static int handle_response(struct coap_client *client, const struct coap_packet *response)
{
	int ret = 0;
	int response_type;
	int block_option;
	int block_num;
	bool blockwise_transfer = false;
	bool last_block = false;
	struct coap_client_internal_request *internal_req;

	/* Handle different types, ACK might be separate or piggybacked
	 * CON and NCON contains a separate response, CON needs an empty response
	 * CON request results as ACK and possibly separate CON or NCON response
	 * NCON request results only as a separate CON or NCON message as there is no ACK
	 * With RESET, just drop gloves and call the callback.
	 */
	response_type = coap_header_get_type(response);

	internal_req = get_request_with_token(client, response);
	/* Reset and Ack need to match the message ID with request */
	if ((response_type == COAP_TYPE_ACK || response_type == COAP_TYPE_RESET) &&
	     internal_req == NULL)  {
		LOG_ERR("Unexpected ACK or Reset");
		return -EFAULT;
	} else if (response_type == COAP_TYPE_RESET) {
		coap_pending_clear(&internal_req->pending);
	}

	/* CON, NON_CON and piggybacked ACK need to match the token with original request */
	uint16_t payload_len;
	uint8_t response_code = coap_header_get_code(response);
	const uint8_t *payload = coap_packet_get_payload(response, &payload_len);

	/* Separate response coming */
	if (payload_len == 0 && response_type == COAP_TYPE_ACK &&
	    response_code == COAP_CODE_EMPTY) {
		internal_req->pending.t0 = k_uptime_get();
		internal_req->pending.timeout = internal_req->pending.t0 + COAP_SEPARATE_TIMEOUT;
		internal_req->pending.retries = 0;
		return 1;
	}

	if (internal_req == NULL || !token_compare(internal_req, response)) {
		LOG_WRN("Not matching tokens");
		return 1;
	}

	/* Received echo option */
	if (find_echo_option(response, &client->echo_option)) {
		 /* Resend request with echo option */
		if (response_code == COAP_RESPONSE_CODE_UNAUTHORIZED) {
			k_mutex_lock(&client->send_mutex, K_FOREVER);

			ret = coap_client_init_request(client, &internal_req->coap_request,
						       internal_req, false);

			if (ret < 0) {
				LOG_ERR("Error creating a CoAP request");
				k_mutex_unlock(&client->send_mutex);
				goto fail;
			}

			ret = coap_packet_append_option(&internal_req->request, COAP_OPTION_ECHO,
							client->echo_option.value,
							client->echo_option.len);
			if (ret < 0) {
				LOG_ERR("Failed to append echo option");
				k_mutex_unlock(&client->send_mutex);
				goto fail;
			}

			if (coap_header_get_type(&internal_req->request) == COAP_TYPE_CON) {
				struct coap_transmission_parameters params =
					internal_req->pending.params;
				ret = coap_pending_init(&internal_req->pending,
							&internal_req->request, &client->address,
							&params);
				if (ret < 0) {
					LOG_ERR("Error creating pending");
					k_mutex_unlock(&client->send_mutex);
					goto fail;
				}

				coap_pending_cycle(&internal_req->pending);
			}

			ret = send_request(client->fd, internal_req->request.data,
					   internal_req->request.offset, 0, &client->address,
					   client->socklen);
			k_mutex_unlock(&client->send_mutex);

			if (ret < 0) {
				LOG_ERR("Error sending a CoAP request");
				goto fail;
			} else {
				return 1;
			}
		} else {
			/* Send echo in next request */
			client->send_echo = true;
		}
	}

	/* Send ack for CON */
	if (response_type == COAP_TYPE_CON) {
		/* CON response is always a separate response, respond with empty ACK. */
		ret = send_ack(client, response, COAP_CODE_EMPTY);
		if (ret < 0) {
			goto fail;
		}
	}

	if (internal_req->pending.timeout != 0) {
		coap_pending_clear(&internal_req->pending);
	}

	/* Check if block2 exists */
	block_option = coap_get_option_int(response, COAP_OPTION_BLOCK2);
	if (block_option > 0) {
		blockwise_transfer = true;
		last_block = !GET_MORE(block_option);
		block_num = GET_BLOCK_NUM(block_option);

		if (block_num == 0) {
			coap_block_transfer_init(&internal_req->recv_blk_ctx,
						 coap_client_default_block_size(),
						 0);
			internal_req->offset = 0;
		}

		ret = coap_update_from_block(response, &internal_req->recv_blk_ctx);
		if (ret < 0) {
			LOG_ERR("Error updating block context");
		}
		coap_next_block(response, &internal_req->recv_blk_ctx);
	} else {
		internal_req->offset = 0;
		last_block = true;
	}

	/* Check if this was a response to last blockwise send */
	if (internal_req->send_blk_ctx.total_size > 0) {
		blockwise_transfer = true;
		internal_req->offset = internal_req->send_blk_ctx.current;
		if (internal_req->send_blk_ctx.total_size == internal_req->send_blk_ctx.current) {
			last_block = true;
		} else {
			last_block = false;
		}
	}

	/* Call user callback */
	if (internal_req->coap_request.cb) {
		internal_req->coap_request.cb(response_code, internal_req->offset, payload,
					      payload_len, last_block,
					      internal_req->coap_request.user_data);

		/* Update the offset for next callback in a blockwise transfer */
		if (blockwise_transfer) {
			internal_req->offset += payload_len;
		}
	}

	/* If this wasn't last block, send the next request */
	if (blockwise_transfer && !last_block) {
		k_mutex_lock(&client->send_mutex, K_FOREVER);
		ret = coap_client_init_request(client, &internal_req->coap_request, internal_req,
					       false);

		if (ret < 0) {
			LOG_ERR("Error creating a CoAP request");
			k_mutex_unlock(&client->send_mutex);
			goto fail;
		}

		struct coap_transmission_parameters params = internal_req->pending.params;
		ret = coap_pending_init(&internal_req->pending, &internal_req->request,
					&client->address, &params);
		if (ret < 0) {
			LOG_ERR("Error creating pending");
			k_mutex_unlock(&client->send_mutex);
			goto fail;
		}
		coap_pending_cycle(&internal_req->pending);

		ret = send_request(client->fd, internal_req->request.data,
				   internal_req->request.offset, 0, &client->address,
				   client->socklen);
		k_mutex_unlock(&client->send_mutex);

		if (ret < 0) {
			LOG_ERR("Error sending a CoAP request");
			goto fail;
		} else {
			return 1;
		}
	}
fail:
	client->response_ready = false;
	internal_req->request_ongoing = false;
	return ret;
}

void coap_client_recv(void *coap_cl, void *a, void *b)
{
	int ret;

	k_sem_take(&coap_client_recv_sem, K_FOREVER);
	while (true) {
		atomic_set(&coap_client_recv_active, 1);
		ret = handle_poll();
		if (ret < 0) {
			/* Error in polling */
			LOG_ERR("Error in poll");
			goto idle;
		}

		for (int i = 0; i < num_clients; i++) {
			if (clients[i]->response_ready) {
				struct coap_packet response;

				ret = recv_response(clients[i], &response);
				if (ret < 0) {
					LOG_ERR("Error receiving response");
					clients[i]->response_ready = false;
					continue;
				}

				ret = handle_response(clients[i], &response);
				if (ret < 0) {
					LOG_ERR("Error handling response");
				}

				clients[i]->response_ready = false;
			}
		}

		/* There are more messages coming */
		if (has_ongoing_requests()) {
			continue;
		} else {
idle:
			atomic_set(&coap_client_recv_active, 0);
			k_sem_take(&coap_client_recv_sem, K_FOREVER);
		}
	}
}

int coap_client_init(struct coap_client *client, const char *info)
{
	if (client == NULL) {
		return -EINVAL;
	}

	if (num_clients >= CONFIG_COAP_CLIENT_MAX_INSTANCES) {
		return -ENOSPC;
	}

	k_mutex_init(&client->send_mutex);

	clients[num_clients] = client;
	num_clients++;

	return 0;
}


K_THREAD_DEFINE(coap_client_recv_thread, CONFIG_COAP_CLIENT_STACK_SIZE,
		coap_client_recv, NULL, NULL, NULL,
		CONFIG_COAP_CLIENT_THREAD_PRIORITY, 0, 0);
