/*
 * Copyright (c) 2022 Martin Jäger <martin@libre.solar>
 * Copyright (c) 2022 tado GmbH
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include "lorawan_services.h"

#include <zephyr/init.h>
#include <zephyr/kernel.h>
#include <zephyr/logging/log.h>

LOG_MODULE_REGISTER(lorawan_services, CONFIG_LORAWAN_SERVICES_LOG_LEVEL);

struct service_uplink_msg {
	sys_snode_t node;
	/* absolute ticks when this message should be scheduled */
	int64_t ticks;
	/* sufficient space for up to 3 answers (max 6 bytes each) */
	uint8_t data[18];
	uint8_t len;
	uint8_t port;
	bool used;
};

K_THREAD_STACK_DEFINE(thread_stack_area, CONFIG_LORAWAN_SERVICES_THREAD_STACK_SIZE);

/*
 * The services need a dedicated work queue, as the LoRaWAN stack uses the system
 * work queue and gets blocked if other LoRaWAN messages are sent and processed from
 * the system work queue in parallel.
 */
static struct k_work_q services_workq;

static struct k_work_delayable uplink_work;

/* Number of active class C sessions and mutex to protect access to session info */
static uint8_t active_class_c_sessions;
static struct k_mutex session_mutex;

/* single-linked list (with pointers) and array for implementation of priority queue */
static struct service_uplink_msg messages[10];
static sys_slist_t msg_list;
static struct k_sem msg_sem;

static void uplink_handler(struct k_work *work)
{
	struct service_uplink_msg msg_copy;
	struct service_uplink_msg *first;
	sys_snode_t *node;
	int err;

	ARG_UNUSED(work);

	/* take semaphore and create a copy of the next message */
	k_sem_take(&msg_sem, K_FOREVER);

	node = sys_slist_get(&msg_list);
	if (node == NULL) {
		goto out;
	}

	first = CONTAINER_OF(node, struct service_uplink_msg, node);
	msg_copy = *first;
	first->used = false;
	sys_slist_remove(&msg_list, NULL, &first->node);

	/* semaphore must be given back before calling lorawan_send */
	k_sem_give(&msg_sem);

	err = lorawan_send(msg_copy.port, msg_copy.data, msg_copy.len, LORAWAN_MSG_UNCONFIRMED);
	if (!err) {
		LOG_DBG("Message sent to port %d", msg_copy.port);
	} else {
		LOG_ERR("Sending message to port %d failed: %d",
			msg_copy.port, err);
	}

	/* take the semaphore again to schedule next uplink */
	k_sem_take(&msg_sem, K_FOREVER);

	node = sys_slist_peek_head(&msg_list);
	if (node == NULL) {
		goto out;
	}
	first = CONTAINER_OF(node, struct service_uplink_msg, node);
	k_work_reschedule_for_queue(&services_workq, &uplink_work,
		K_TIMEOUT_ABS_TICKS(first->ticks));

out:
	k_sem_give(&msg_sem);
}

static inline void insert_uplink(struct service_uplink_msg *msg_new)
{
	struct service_uplink_msg *msg_prev;

	if (sys_slist_is_empty(&msg_list)) {
		sys_slist_append(&msg_list, &msg_new->node);
	} else {
		int count = 0;

		SYS_SLIST_FOR_EACH_CONTAINER(&msg_list, msg_prev, node) {
			count++;
			if (msg_prev->ticks <= msg_new->ticks) {
				break;
			}
		}
		if (msg_prev != NULL) {
			sys_slist_insert(&msg_list, &msg_prev->node, &msg_new->node);
		} else {
			sys_slist_append(&msg_list, &msg_new->node);
		}
	}
}

int lorawan_services_schedule_uplink(uint8_t port, uint8_t *data, uint8_t len, uint32_t timeout)
{
	struct service_uplink_msg *next;
	int64_t timeout_abs_ticks;

	if (len > sizeof(messages[0].data)) {
		LOG_ERR("Uplink payload for port %u too long: %u bytes", port, len);
		LOG_HEXDUMP_ERR(data, len, "Payload: ");
		return -EFBIG;
	}

	timeout_abs_ticks = k_uptime_ticks() + k_ms_to_ticks_ceil64(timeout);

	k_sem_take(&msg_sem, K_FOREVER);

	for (int i = 0; i < ARRAY_SIZE(messages); i++) {
		if (!messages[i].used) {
			memcpy(messages[i].data, data, len);
			messages[i].port = port;
			messages[i].len = len;
			messages[i].ticks = timeout_abs_ticks;
			messages[i].used = true;

			insert_uplink(&messages[i]);

			next = SYS_SLIST_PEEK_HEAD_CONTAINER(&msg_list, next, node);
			if (next != NULL) {
				k_work_reschedule_for_queue(&services_workq, &uplink_work,
					K_TIMEOUT_ABS_TICKS(next->ticks));
			}

			k_sem_give(&msg_sem);

			return 0;
		}
	}

	k_sem_give(&msg_sem);

	LOG_WRN("Message queue full, message for port %u dropped.", port);

	return -ENOSPC;
}

int lorawan_services_reschedule_work(struct k_work_delayable *dwork, k_timeout_t delay)
{
	return k_work_reschedule_for_queue(&services_workq, dwork, delay);
}

int lorawan_services_class_c_start(void)
{
	int ret;

	k_mutex_lock(&session_mutex, K_FOREVER);

	if (active_class_c_sessions == 0) {
		ret = lorawan_set_class(LORAWAN_CLASS_C);
		if (ret == 0) {
			LOG_DBG("Switched to class C");
			active_class_c_sessions++;
			ret = active_class_c_sessions;
		}
	} else {
		active_class_c_sessions++;
		ret = active_class_c_sessions;
	}

	k_mutex_unlock(&session_mutex);

	return ret;
}

int lorawan_services_class_c_stop(void)
{
	int ret = 0;

	k_mutex_lock(&session_mutex, K_FOREVER);

	if (active_class_c_sessions == 1) {
		ret = lorawan_set_class(LORAWAN_CLASS_A);
		if (ret == 0) {
			LOG_DBG("Reverted to class A");
			active_class_c_sessions--;
		}
	} else if (active_class_c_sessions > 1) {
		active_class_c_sessions--;
		ret = active_class_c_sessions;
	}

	k_mutex_unlock(&session_mutex);

	return ret;
}

int lorawan_services_class_c_active(void)
{
	return active_class_c_sessions;
}

static int lorawan_services_init(void)
{

	sys_slist_init(&msg_list);
	k_sem_init(&msg_sem, 1, 1);

	k_work_queue_init(&services_workq);
	k_work_queue_start(&services_workq,
			   thread_stack_area, K_THREAD_STACK_SIZEOF(thread_stack_area),
			   CONFIG_LORAWAN_SERVICES_THREAD_PRIORITY, NULL);

	k_work_init_delayable(&uplink_work, uplink_handler);

	k_mutex_init(&session_mutex);

	k_thread_name_set(&services_workq.thread, "lorawan_services");

	return 0;
}

SYS_INIT(lorawan_services_init, APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
