/*
 * Copyright (c) 2025 Embeint Inc
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <zephyr/net_buf.h>
#include <zephyr/logging/log.h>
#include <zephyr/drivers/uart.h>
#include <zephyr/random/random.h>

/* change this to any other UART peripheral if desired */
#define UART_DEVICE_NODE DT_CHOSEN(zephyr_shell_uart)

// /* Maximum number of packets to generate per iteration */
// #define LOOP_ITER_MAX_TX 4
// /* Maximum size of our TX packets */
// #define MAX_TX_LEN 32
// #define RX_CHUNK_LEN 32

// /* Buffer pool for our TX payloads */
// NET_BUF_POOL_DEFINE(tx_pool, LOOP_ITER_MAX_TX, MAX_TX_LEN, 0, NULL);

// struct k_fifo tx_queue;
// struct net_buf *tx_pending_buffer;
// uint8_t async_rx_buffer[2][RX_CHUNK_LEN];
// volatile uint8_t async_rx_buffer_idx;

static const struct device *const uart_dev = DEVICE_DT_GET(UART_DEVICE_NODE);

LOG_MODULE_REGISTER(sample, LOG_LEVEL_INF);

// static void uart_callback(const struct device *dev, struct uart_event *evt, void *user_data)
// {
// 	struct net_buf *buf;
// 	int rc;

// 	LOG_DBG("EVENT: %d", evt->type);

// 	switch (evt->type) {
// 	case UART_TX_DONE:
// 		LOG_DBG("TX complete %p", tx_pending_buffer);

// 		/* Free TX buffer */
// 		net_buf_unref(tx_pending_buffer);
// 		tx_pending_buffer = NULL;

// 		/* Handle any queued buffers */
// 		buf = k_fifo_get(&tx_queue, K_NO_WAIT);
// 		if (buf != NULL) {
// 			rc = uart_tx(dev, buf->data, buf->len, 0);
// 			if (rc != 0) {
// 				LOG_ERR("TX from ISR failed (%d)", rc);
// 				net_buf_unref(buf);
// 			} else {
// 				tx_pending_buffer = buf;
// 			}
// 		}
// 		break;
// 	case UART_RX_BUF_REQUEST:
// 		/* Return the next buffer index */
// 		LOG_DBG("Providing buffer index %d", async_rx_buffer_idx);
// 		rc = uart_rx_buf_rsp(dev, async_rx_buffer[async_rx_buffer_idx],
// 				     sizeof(async_rx_buffer[0]));
// 		__ASSERT_NO_MSG(rc == 0);
// 		async_rx_buffer_idx = async_rx_buffer_idx ? 0 : 1;
// 		break;
// 	case UART_RX_BUF_RELEASED:
// 	case UART_RX_DISABLED:
// 		break;
// 	case UART_RX_RDY:
// 		LOG_HEXDUMP_INF(evt->data.rx.buf + evt->data.rx.offset,
// 				evt->data.rx.len, "RX_RDY");
// 		break;
// 	default:
// 		LOG_WRN("Unhandled event %d", evt->type);
// 	}
// }

// int main(void)
// {
// 	bool rx_enabled = false;
// 	struct net_buf *tx_buf;
// 	int loop_counter = 0;
// 	uint8_t num_tx;
// 	int tx_len;
// 	int rc;

// 	/* Register the async interrupt handler */
// 	uart_callback_set(uart_dev, uart_callback, (void *)uart_dev);

// 	while (1) {
// 		/* Wait a while until the next burst transmission */
// 		k_sleep(K_SECONDS(5));

// 		/* Each loop, try to send a random number of packets */
// 		num_tx = (sys_rand32_get() % LOOP_ITER_MAX_TX) + 1;
// 		LOG_INF("Loop %d: Sending %d packets", loop_counter, num_tx);
// 		for (int i = 0; i < num_tx; i++) {
// 			/* Allocate the data packet */
// 			tx_buf = net_buf_alloc(&tx_pool, K_FOREVER);
// 			/* Populate it with data */
// 			tx_len = snprintk(tx_buf->data, net_buf_tailroom(tx_buf),
// 					  "Loop %d: Packet: %d\r\n", loop_counter, i);
// 			net_buf_add(tx_buf, tx_len);

// 			/* Queue packet for transmission */
// 			rc = uart_tx(uart_dev, tx_buf->data, tx_buf->len, SYS_FOREVER_US);
// 			if (rc == 0) {
// 				/* Store the pending buffer */
// 				tx_pending_buffer = tx_buf;
// 			} else if (rc == -EBUSY) {
// 				/* Transmission is already in progress */
// 				LOG_DBG("Queuing buffer %p", tx_buf);
// 				k_fifo_put(&tx_queue, tx_buf);
// 			} else {
// 				LOG_ERR("Unknown error (%d)", rc);
// 			}
// 		}

// 		/* Toggle the RX state */
// 		if (rx_enabled) {
// 			uart_rx_disable(uart_dev);
// 		} else {
// 			async_rx_buffer_idx = 1;
// 			uart_rx_enable(uart_dev, async_rx_buffer[0], RX_CHUNK_LEN, 100);
// 		}
// 		rx_enabled = !rx_enabled;
// 		LOG_INF("RX is now %s", rx_enabled ? "enabled" : "disabled");

// 		loop_counter += 1;
// 	}
// }


static bool TX_DONE = 1;
// static uint8_t tx_buf[] =   {"nRF Connect SDK Fundamentals Course\r\n"
//                              "Press 0-2 on your keyboard to toggle LEDS 0-2 on your development kit\r\n"};
#define RECEIVE_BUFF_SIZE 256
static uint8_t rx_buf[RECEIVE_BUFF_SIZE] = {0};
#define RECEIVE_TIMEOUT 100

static void uart_callback(const struct device *dev, struct uart_event *evt, void *user_data)
{
	switch (evt->type) {
	
	case UART_TX_DONE:
		// do something
		TX_DONE = 1;

		break;

	case UART_TX_ABORTED:
		// do something
		break;
		
	case UART_RX_RDY:
		// do something
		if(TX_DONE == 1)
		{
			uart_tx(uart_dev, &evt->data.rx.buf[evt->data.rx.offset], evt->data.rx.len, SYS_FOREVER_US);
			TX_DONE = 0;
		}
		break;

	case UART_RX_BUF_REQUEST:
		// do something
		break;

	case UART_RX_BUF_RELEASED:
		// do something
		break;
		
	case UART_RX_DISABLED:
		// do something
		uart_rx_enable(dev, rx_buf, sizeof rx_buf, RECEIVE_TIMEOUT);
		break;

	case UART_RX_STOPPED:
		// do something
		break;
		
	default:
		break;
	}
}

int main(void)
{	
	int ret;
	uart_callback_set(uart_dev, uart_callback, (void *)uart_dev);
	ret = uart_rx_enable(uart_dev ,rx_buf,sizeof rx_buf,RECEIVE_TIMEOUT);
	if (ret) {
		return 1;
	}

	while (1) 
	{

	}


}