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

#include <string.h>
#include <zephyr/drivers/uart.h>
#include <zephyr/drivers/serial/uart_async_rx.h>

static uint8_t inc(struct uart_async_rx *rx_data, uint8_t val)
{
	return (val + 1) & (rx_data->config->buf_cnt - 1);
}

static struct uart_async_rx_buf *get_buf(struct uart_async_rx *rx_data, uint8_t idx)
{
	uint8_t *p = rx_data->config->buffer;

	p += idx * (rx_data->buf_len + sizeof(struct uart_async_rx_buf));

	return (struct uart_async_rx_buf *)p;
}

uint8_t *uart_async_rx_buf_req(struct uart_async_rx *rx_data)
{
	uint8_t *data = NULL;

	if (rx_data->free_buf_cnt != 0) {
		struct uart_async_rx_buf *buf = get_buf(rx_data, rx_data->drv_buf_idx);

		data = buf->buffer;
		rx_data->drv_buf_idx = inc(rx_data, rx_data->drv_buf_idx);

		atomic_dec(&rx_data->free_buf_cnt);
	}

	return data;
}

void uart_async_rx_on_rdy(struct uart_async_rx *rx_data, uint8_t *buffer, size_t length)
{
	/* Cannot use CONTAINER_OF because validation fails due to type mismatch:
	 * uint8_t * vs uint8_t [].
	 */
	struct uart_async_rx_buf *rx_buf =
		(struct uart_async_rx_buf *)(buffer - offsetof(struct uart_async_rx_buf, buffer));

	rx_buf->wr_idx += length;
	__ASSERT_NO_MSG(rx_buf->wr_idx <= rx_data->buf_len);

	atomic_add(&rx_data->pending_bytes, length);
}

static void buf_reset(struct uart_async_rx_buf *buf)
{
	buf->wr_idx = 0;
	buf->completed = 0;
}

static void usr_rx_buf_release(struct uart_async_rx *rx_data, struct uart_async_rx_buf *buf)
{
	buf_reset(buf);
	rx_data->rd_idx = 0;
	rx_data->rd_buf_idx = inc(rx_data, rx_data->rd_buf_idx);
	atomic_inc(&rx_data->free_buf_cnt);
	__ASSERT_NO_MSG(rx_data->free_buf_cnt <= rx_data->config->buf_cnt);
}

void uart_async_rx_on_buf_rel(struct uart_async_rx *rx_data, uint8_t *buffer)
{
	/* Cannot use CONTAINER_OF because validation fails due to type mismatch:
	 * uint8_t * vs uint8_t [].
	 */
	struct uart_async_rx_buf *rx_buf =
		(struct uart_async_rx_buf *)(buffer - offsetof(struct uart_async_rx_buf, buffer));

	rx_buf->completed = 1;
}

size_t uart_async_rx_data_claim(struct uart_async_rx *rx_data, uint8_t **data, size_t length)
{
	struct uart_async_rx_buf *buf;
	int rem;

	if ((rx_data->pending_bytes == 0) || (length == 0)) {
		return 0;
	}

	do {
		buf = get_buf(rx_data, rx_data->rd_buf_idx);
		/* Even though buffer is released in consume phase it is possible that
		 * it is required here as well (e.g. was not completed previously).
		 */
		if ((buf->completed == 1) && (rx_data->rd_idx == buf->wr_idx)) {
			usr_rx_buf_release(rx_data, buf);
		} else {
			break;
		}
	} while (1);

	*data = &buf->buffer[rx_data->rd_idx];
	rem = buf->wr_idx - rx_data->rd_idx;

	return MIN(length, rem);
}

bool uart_async_rx_data_consume(struct uart_async_rx *rx_data, size_t length)
{
	struct uart_async_rx_buf *buf = get_buf(rx_data, rx_data->rd_buf_idx);

	rx_data->rd_idx += length;
	/* Attempt to release the buffer if it is completed and all data is consumed. */
	if ((buf->completed == 1) && (rx_data->rd_idx == buf->wr_idx)) {
		usr_rx_buf_release(rx_data, buf);
	}

	atomic_sub(&rx_data->pending_bytes, length);

	__ASSERT_NO_MSG(rx_data->rd_idx <= buf->wr_idx);

	return rx_data->free_buf_cnt > 0;
}

void uart_async_rx_reset(struct uart_async_rx *rx_data)
{
	rx_data->free_buf_cnt = rx_data->config->buf_cnt;
	rx_data->rd_idx = 0;
	for (uint8_t i = 0; i < rx_data->config->buf_cnt; i++) {
		buf_reset(get_buf(rx_data, i));
	}
}

int uart_async_rx_init(struct uart_async_rx *rx_data,
		       const struct uart_async_rx_config *config)
{
	__ASSERT_NO_MSG(config->length / config->buf_cnt <= UINT8_MAX);
	memset(rx_data, 0, sizeof(*rx_data));
	rx_data->config = config;
	rx_data->buf_len = (config->length / config->buf_cnt) - UART_ASYNC_RX_BUF_OVERHEAD;

	if (rx_data->buf_len >= BIT(7)) {
		return -EINVAL;
	}
	uart_async_rx_reset(rx_data);

	return 0;
}
