/*
 * Copyright (c) 2023 Trackunit Corporation
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include "modem_backend_uart_async.h"

#include <zephyr/logging/log.h>
LOG_MODULE_DECLARE(modem_backend_uart);

#include <zephyr/kernel.h>
#include <string.h>

#define MODEM_BACKEND_UART_ASYNC_STATE_TRANSMITTING_BIT       (0)
#define MODEM_BACKEND_UART_ASYNC_STATE_RECEIVING_BIT          (1)
#define MODEM_BACKEND_UART_ASYNC_STATE_RX_BUF0_USED_BIT       (2)
#define MODEM_BACKEND_UART_ASYNC_STATE_RX_BUF1_USED_BIT       (3)

static bool modem_backend_uart_async_is_closed(struct modem_backend_uart *backend)
{
	if (!atomic_test_bit(&backend->async.state,
			    MODEM_BACKEND_UART_ASYNC_STATE_TRANSMITTING_BIT) &&
	    !atomic_test_bit(&backend->async.state,
			    MODEM_BACKEND_UART_ASYNC_STATE_RECEIVING_BIT) &&
	    !atomic_test_bit(&backend->async.state,
			    MODEM_BACKEND_UART_ASYNC_STATE_RX_BUF0_USED_BIT) &&
	    !atomic_test_bit(&backend->async.state,
			    MODEM_BACKEND_UART_ASYNC_STATE_RX_BUF1_USED_BIT)) {
		return true;
	}

	return false;
}

static void modem_backend_uart_async_event_handler(const struct device *dev,
						   struct uart_event *evt, void *user_data)
{
	struct modem_backend_uart *backend = (struct modem_backend_uart *) user_data;
	k_spinlock_key_t key;
	uint32_t received;

	switch (evt->type) {
	case UART_TX_DONE:
		atomic_clear_bit(&backend->async.state,
				 MODEM_BACKEND_UART_ASYNC_STATE_TRANSMITTING_BIT);

		break;

	case UART_TX_ABORTED:
		LOG_WRN("Transmit aborted");
		atomic_clear_bit(&backend->async.state,
				 MODEM_BACKEND_UART_ASYNC_STATE_TRANSMITTING_BIT);

		break;

	case UART_RX_BUF_REQUEST:
		if (!atomic_test_and_set_bit(&backend->async.state,
					     MODEM_BACKEND_UART_ASYNC_STATE_RX_BUF0_USED_BIT)) {
			uart_rx_buf_rsp(backend->uart, backend->async.receive_bufs[0],
					backend->async.receive_buf_size);

			break;
		}

		if (!atomic_test_and_set_bit(&backend->async.state,
					     MODEM_BACKEND_UART_ASYNC_STATE_RX_BUF1_USED_BIT)) {
			uart_rx_buf_rsp(backend->uart, backend->async.receive_bufs[1],
					backend->async.receive_buf_size);

			break;
		}

		LOG_WRN("No receive buffer available");
		break;

	case UART_RX_BUF_RELEASED:
		if (evt->data.rx_buf.buf == backend->async.receive_bufs[0]) {
			atomic_clear_bit(&backend->async.state,
					 MODEM_BACKEND_UART_ASYNC_STATE_RX_BUF0_USED_BIT);

			break;
		}

		if (evt->data.rx_buf.buf == backend->async.receive_bufs[1]) {
			atomic_clear_bit(&backend->async.state,
					 MODEM_BACKEND_UART_ASYNC_STATE_RX_BUF1_USED_BIT);

			break;
		}

		LOG_WRN("Unknown receive buffer released");
		break;

	case UART_RX_RDY:
		key = k_spin_lock(&backend->async.receive_rb_lock);
		received = ring_buf_put(&backend->async.receive_rb,
					&evt->data.rx.buf[evt->data.rx.offset],
					evt->data.rx.len);

		if (received < evt->data.rx.len) {
			ring_buf_reset(&backend->async.receive_rb);
			k_spin_unlock(&backend->async.receive_rb_lock, key);
			LOG_WRN("Receive buffer overrun");
			break;
		}

		k_spin_unlock(&backend->async.receive_rb_lock, key);
		k_work_submit(&backend->receive_ready_work);
		break;

	case UART_RX_DISABLED:
		atomic_clear_bit(&backend->async.state,
				 MODEM_BACKEND_UART_ASYNC_STATE_RECEIVING_BIT);
		break;

	case UART_RX_STOPPED:
		LOG_WRN("Receive stopped for reasons: %u", (uint8_t)evt->data.rx_stop.reason);
		break;

	default:
		break;
	}

	if (modem_backend_uart_async_is_closed(backend)) {
		k_work_submit(&backend->async.rx_disabled_work);
	}
}

static int modem_backend_uart_async_open(void *data)
{
	struct modem_backend_uart *backend = (struct modem_backend_uart *)data;
	int ret;

	atomic_set(&backend->async.state, 0);
	ring_buf_reset(&backend->async.receive_rb);

	/* Reserve receive buffer 0 */
	atomic_set_bit(&backend->async.state,
		       MODEM_BACKEND_UART_ASYNC_STATE_RX_BUF0_USED_BIT);

	/*
	 * Receive buffer 0 is used internally by UART, receive ring buffer 0 is
	 * used to store received data.
	 */
	ret = uart_rx_enable(backend->uart, backend->async.receive_bufs[0],
			     backend->async.receive_buf_size,
			     CONFIG_MODEM_BACKEND_UART_ASYNC_RECEIVE_IDLE_TIMEOUT_MS * 1000L);

	if (ret < 0) {
		return ret;
	}

	atomic_set_bit(&backend->async.state,
		       MODEM_BACKEND_UART_ASYNC_STATE_RECEIVING_BIT);

	modem_pipe_notify_opened(&backend->pipe);
	return 0;
}

static int modem_backend_uart_async_transmit(void *data, const uint8_t *buf, size_t size)
{
	struct modem_backend_uart *backend = (struct modem_backend_uart *)data;
	bool transmitting;
	uint32_t bytes_to_transmit;
	int ret;

	transmitting = atomic_test_and_set_bit(&backend->async.state,
					       MODEM_BACKEND_UART_ASYNC_STATE_TRANSMITTING_BIT);

	if (transmitting) {
		return 0;
	}

	/* Determine amount of bytes to transmit */
	bytes_to_transmit = (size < backend->async.transmit_buf_size)
			  ? size
			  : backend->async.transmit_buf_size;

	/* Copy buf to transmit buffer which is passed to UART */
	memcpy(backend->async.transmit_buf, buf, bytes_to_transmit);

	ret = uart_tx(backend->uart, backend->async.transmit_buf, bytes_to_transmit,
		      CONFIG_MODEM_BACKEND_UART_ASYNC_TRANSMIT_TIMEOUT_MS * 1000L);

	if (ret < 0) {
		LOG_WRN("Failed to start async transmit");
		return ret;
	}

	return (int)bytes_to_transmit;
}

static int modem_backend_uart_async_receive(void *data, uint8_t *buf, size_t size)
{
	struct modem_backend_uart *backend = (struct modem_backend_uart *)data;
	k_spinlock_key_t key;
	uint32_t received;
	bool empty;

	key = k_spin_lock(&backend->async.receive_rb_lock);
	received = ring_buf_get(&backend->async.receive_rb, buf, size);
	empty = ring_buf_is_empty(&backend->async.receive_rb);
	k_spin_unlock(&backend->async.receive_rb_lock, key);

	if (!empty) {
		k_work_submit(&backend->receive_ready_work);
	}

	return (int)received;
}

static int modem_backend_uart_async_close(void *data)
{
	struct modem_backend_uart *backend = (struct modem_backend_uart *)data;

	uart_tx_abort(backend->uart);
	uart_rx_disable(backend->uart);
	return 0;
}

struct modem_pipe_api modem_backend_uart_async_api = {
	.open = modem_backend_uart_async_open,
	.transmit = modem_backend_uart_async_transmit,
	.receive = modem_backend_uart_async_receive,
	.close = modem_backend_uart_async_close,
};

bool modem_backend_uart_async_is_supported(struct modem_backend_uart *backend)
{
	return uart_callback_set(backend->uart, modem_backend_uart_async_event_handler,
				 backend) == 0;
}

static void modem_backend_uart_async_notify_closed(struct k_work *item)
{
	struct modem_backend_uart_async *async =
		CONTAINER_OF(item, struct modem_backend_uart_async, rx_disabled_work);

	struct modem_backend_uart *backend =
		CONTAINER_OF(async, struct modem_backend_uart, async);

	modem_pipe_notify_closed(&backend->pipe);
}

void modem_backend_uart_async_init(struct modem_backend_uart *backend,
				   const struct modem_backend_uart_config *config)
{
	uint32_t receive_buf_size_quarter = config->receive_buf_size / 4;

	/* Use half the receive buffer for UART receive buffers */
	backend->async.receive_buf_size = receive_buf_size_quarter;
	backend->async.receive_bufs[0] = &config->receive_buf[0];
	backend->async.receive_bufs[1] = &config->receive_buf[receive_buf_size_quarter];

	/* Use half the receive buffer for the received data ring buffer */
	ring_buf_init(&backend->async.receive_rb, (receive_buf_size_quarter * 2),
		      &config->receive_buf[receive_buf_size_quarter * 2]);

	backend->async.transmit_buf = config->transmit_buf;
	backend->async.transmit_buf_size = config->transmit_buf_size;
	k_work_init(&backend->async.rx_disabled_work, modem_backend_uart_async_notify_closed);
	modem_pipe_init(&backend->pipe, backend, &modem_backend_uart_async_api);
}
