/*
 * Copyright (c) 2020 Siddharth Chandrasekaran <siddharth@embedjournal.com>
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <zephyr/kernel.h>
#include <zephyr/init.h>
#include <zephyr/device.h>
#include <zephyr/drivers/uart.h>
#include <zephyr/sys/ring_buffer.h>
#include <zephyr/logging/log.h>

#include "osdp_common.h"

LOG_MODULE_REGISTER(osdp, CONFIG_OSDP_LOG_LEVEL);

#ifdef CONFIG_OSDP_SC_ENABLED
#ifdef CONFIG_OSDP_MODE_PD
#define OSDP_KEY_STRING CONFIG_OSDP_PD_SCBK
#else
#define OSDP_KEY_STRING CONFIG_OSDP_MASTER_KEY
#endif
#else
#define OSDP_KEY_STRING ""
#endif	/* CONFIG_OSDP_SC_ENABLED */

struct osdp_device {
	struct ring_buf rx_buf;
	struct ring_buf tx_buf;
#ifdef CONFIG_OSDP_MODE_PD
	int rx_event_data;
	struct k_fifo rx_event_fifo;
#endif
	uint8_t rx_fbuf[CONFIG_OSDP_UART_BUFFER_LENGTH];
	uint8_t tx_fbuf[CONFIG_OSDP_UART_BUFFER_LENGTH];
	struct uart_config dev_config;
	const struct device *dev;
	int wait_for_mark;
	uint8_t last_byte;
};

static struct osdp osdp_ctx;
static struct osdp_cp osdp_cp_ctx;
static struct osdp_pd osdp_pd_ctx[CONFIG_OSDP_NUM_CONNECTED_PD];
static struct osdp_device osdp_device;
static struct k_thread osdp_refresh_thread;
static K_THREAD_STACK_DEFINE(osdp_thread_stack, CONFIG_OSDP_THREAD_STACK_SIZE);

static void osdp_handle_in_byte(struct osdp_device *p, uint8_t *buf, int len)
{
	if (p->wait_for_mark) {
		/* Check for new packet beginning with [FF,53,...] sequence */
		if (p->last_byte == 0xFF && buf[0] == 0x53) {
			buf[0] = 0xFF;
			ring_buf_put(&p->rx_buf, buf, 1);   /* put last byte */
			buf[0] = 0x53;
			ring_buf_put(&p->rx_buf, buf, len); /* put rest */
			p->wait_for_mark = 0; /* Mark found. Clear flag */
		}
		p->last_byte = buf[0];
		return;
	}
	ring_buf_put(&p->rx_buf, buf, len);
}

static void osdp_uart_isr(const struct device *dev, void *user_data)
{
	size_t len;
	uint8_t buf[64];
	struct osdp_device *p = user_data;

	while (uart_irq_update(dev) && uart_irq_is_pending(dev)) {

		if (uart_irq_rx_ready(dev)) {
			len = uart_fifo_read(dev, buf, sizeof(buf));
			if (len > 0) {
				osdp_handle_in_byte(p, buf, len);
			}
		}

		if (uart_irq_tx_ready(dev)) {
			len = ring_buf_get(&p->tx_buf, buf, 1);
			if (!len) {
				uart_irq_tx_disable(dev);
			} else {
				uart_fifo_fill(dev, buf, 1);
			}
		}
	}
#ifdef CONFIG_OSDP_MODE_PD
	if (p->wait_for_mark == 0) {
		/* wake osdp_refresh thread */
		k_fifo_put(&p->rx_event_fifo, &p->rx_event_data);
	}
#endif
}

static int osdp_uart_receive(void *data, uint8_t *buf, int len)
{
	struct osdp_device *p = data;

	return (int)ring_buf_get(&p->rx_buf, buf, len);
}

static int osdp_uart_send(void *data, uint8_t *buf, int len)
{
	int sent = 0;
	struct osdp_device *p = data;

	sent = (int)ring_buf_put(&p->tx_buf, buf, len);
	uart_irq_tx_enable(p->dev);
	return sent;
}

static void osdp_uart_flush(void *data)
{
	struct osdp_device *p = data;

	p->wait_for_mark = 1;
	ring_buf_reset(&p->tx_buf);
	ring_buf_reset(&p->rx_buf);
}

struct osdp *osdp_get_ctx()
{
	return &osdp_ctx;
}

static struct osdp *osdp_build_ctx(struct osdp_channel *channel)
{
	int i;
	struct osdp *ctx;
	struct osdp_pd *pd;
	int pd_adddres[CONFIG_OSDP_NUM_CONNECTED_PD] = {0};

#ifdef CONFIG_OSDP_MODE_PD
	pd_adddres[0] = CONFIG_OSDP_PD_ADDRESS;
#else
	if (osdp_extract_address(pd_adddres)) {
		return NULL;
	}
#endif
	ctx = &osdp_ctx;
	ctx->cp = &osdp_cp_ctx;
	ctx->cp->__parent = ctx;
	ctx->cp->num_pd = CONFIG_OSDP_NUM_CONNECTED_PD;
	ctx->pd = &osdp_pd_ctx[0];
	SET_CURRENT_PD(ctx, 0);

	for (i = 0; i < CONFIG_OSDP_NUM_CONNECTED_PD; i++) {
		pd = TO_PD(ctx, i);
		pd->offset = i;
		pd->seq_number = -1;
		pd->__parent = ctx;
		pd->address = pd_adddres[i];
		pd->baud_rate = CONFIG_OSDP_UART_BAUD_RATE;
		memcpy(&pd->channel, channel, sizeof(struct osdp_channel));
		k_mem_slab_init(&pd->cmd.slab,
				pd->cmd.slab_buf, sizeof(struct osdp_cmd),
				CONFIG_OSDP_PD_COMMAND_QUEUE_SIZE);
	}
	return ctx;
}

void osdp_refresh(void *arg1, void *arg2, void *arg3)
{
	struct osdp *ctx = osdp_get_ctx();

	while (1) {
#ifdef CONFIG_OSDP_MODE_PD
		k_fifo_get(&osdp_device.rx_event_fifo, K_FOREVER);
#else
		k_msleep(50);
#endif
		osdp_update(ctx);
	}
}

static int osdp_init(const struct device *arg)
{
	ARG_UNUSED(arg);
	int len;
	uint8_t c, *key = NULL, key_buf[16];
	struct osdp *ctx;
	struct osdp_device *p = &osdp_device;
	struct osdp_channel channel = {
		.send = osdp_uart_send,
		.recv = osdp_uart_receive,
		.flush = osdp_uart_flush,
		.data = &osdp_device,
	};

#ifdef CONFIG_OSDP_MODE_PD
	k_fifo_init(&p->rx_event_fifo);
#endif

	ring_buf_init(&p->rx_buf, sizeof(p->rx_fbuf), p->rx_fbuf);
	ring_buf_init(&p->tx_buf, sizeof(p->tx_fbuf), p->tx_fbuf);

	/* init OSDP uart device */
	p->dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_osdp_uart));
	if (!device_is_ready(p->dev)) {
		LOG_ERR("UART dev is not ready");
		k_panic();
	}

	/* configure uart device to 8N1 */
	p->dev_config.baudrate = CONFIG_OSDP_UART_BAUD_RATE;
	p->dev_config.data_bits = UART_CFG_DATA_BITS_8;
	p->dev_config.parity = UART_CFG_PARITY_NONE;
	p->dev_config.stop_bits = UART_CFG_STOP_BITS_1;
	p->dev_config.flow_ctrl = UART_CFG_FLOW_CTRL_NONE;
	uart_configure(p->dev, &p->dev_config);

	uart_irq_rx_disable(p->dev);
	uart_irq_tx_disable(p->dev);
	uart_irq_callback_user_data_set(p->dev, osdp_uart_isr, p);

	/* Drain UART fifo and set channel to wait for mark byte */
	while (uart_irq_rx_ready(p->dev)) {
		uart_fifo_read(p->dev, &c, 1);
	}
	p->wait_for_mark = 1;

	/* Both TX and RX are interrupt driven */
	uart_irq_rx_enable(p->dev);

	/* setup OSDP */
	ctx = osdp_build_ctx(&channel);
	if (ctx == NULL) {
		LOG_ERR("OSDP build ctx failed!");
		k_panic();
	}

	if (IS_ENABLED(CONFIG_OSDP_SC_ENABLED)) {
		if (strcmp(OSDP_KEY_STRING, "NONE") != 0) {
			len = strlen(OSDP_KEY_STRING);
			if (len != 32) {
				LOG_ERR("Key string length must be 32");
				k_panic();
			}
			len = hex2bin(OSDP_KEY_STRING, 32, key_buf, 16);
			if (len != 16) {
				LOG_ERR("Failed to parse key buffer");
				k_panic();
			}
			key = key_buf;
		}
	}

	if (osdp_setup(ctx, key)) {
		LOG_ERR("Failed to setup OSDP device!");
		k_panic();
	}

	LOG_INF("OSDP init okay!");

	/* kick off refresh thread */
	k_thread_create(&osdp_refresh_thread, osdp_thread_stack,
			CONFIG_OSDP_THREAD_STACK_SIZE, osdp_refresh,
			NULL, NULL, NULL, K_PRIO_COOP(2), 0, K_NO_WAIT);
	return 0;
}

SYS_INIT(osdp_init, POST_KERNEL, 10);
