/*
 * Copyright (c) 2023 Intel Corporation.
 *
 * SPDX-License-Identifier: Apache-2.0
 */
#include <zephyr/sys/__assert.h>
#include <zephyr/devicetree.h>
#include <zephyr/drivers/sensor.h>
#include <zephyr/init.h>
#include <zephyr/kernel.h>
#include <zephyr/rtio/rtio.h>
#include <zephyr/sensing/sensing.h>
#include <zephyr/sensing/sensing_sensor.h>
#include <zephyr/logging/log.h>
#include <stdlib.h>
#include "sensor_mgmt.h"

#define DT_DRV_COMPAT zephyr_sensing

BUILD_ASSERT(DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT) == 1,
	     "only one 'zephyr_sensing' compatible node may be present");

LOG_MODULE_REGISTER(sensing, CONFIG_SENSING_LOG_LEVEL);

static struct sensing_context sensing_ctx = {
};
RTIO_DEFINE_WITH_MEMPOOL(sensing_rtio_ctx, CONFIG_SENSING_RTIO_SQE_NUM,
		CONFIG_SENSING_RTIO_CQE_NUM,
		CONFIG_SENSING_RTIO_BLOCK_COUNT,
		CONFIG_SENSING_RTIO_BLOCK_SIZE, 4);

static enum sensor_channel sensing_sensor_type_to_chan(const int32_t type)
{
	switch (type) {
	case SENSING_SENSOR_TYPE_MOTION_ACCELEROMETER_3D:
		return SENSOR_CHAN_ACCEL_XYZ;
	case SENSING_SENSOR_TYPE_MOTION_GYROMETER_3D:
		return SENSOR_CHAN_GYRO_XYZ;
	default:
		break;
	}

	return SENSOR_CHAN_PRIV_START;
}

/* sensor_later_config including arbitrate/set interval/sensitivity
 */
static uint32_t arbitrate_interval(struct sensing_sensor *sensor)
{
	struct sensing_connection *conn;
	uint32_t min_interval = UINT32_MAX;
	uint32_t interval;

	/* search from all clients, arbitrate the interval */
	for_each_client_conn(sensor, conn) {
		LOG_INF("arbitrate interval, sensor:%s for each conn:%p, interval:%d(us)",
			sensor->dev->name, conn, conn->interval);
		if (!is_client_request_data(conn)) {
			continue;
		}
		if (conn->interval < min_interval) {
			min_interval = conn->interval;
		}
	}
	/* min_interval == UINT32_MAX means sensor is not opened by any clients,
	 * then interval should be 0
	 */
	interval = (min_interval == UINT32_MAX ? 0 : min_interval);

	LOG_DBG("arbitrate interval, sensor:%s, interval:%d(us)",
			sensor->dev->name, interval);

	return interval;
}

static int set_arbitrate_interval(struct sensing_sensor *sensor, uint32_t interval)
{
	struct sensing_submit_config *config = sensor->iodev->data;
	struct sensor_value odr = {0};
	int ret;

	__ASSERT(sensor && sensor->dev, "set arbitrate interval, sensor or sensor device is NULL");

	LOG_INF("set arbitrate interval:%d, sensor:%s, is_streaming:%d",
			interval, sensor->dev->name, config->is_streaming);

	if (interval) {
		odr.val1 = USEC_PER_SEC / interval;
		odr.val2 = (uint64_t)USEC_PER_SEC * 1000000 / interval % 1000000;
	}

	ret = sensor_attr_set(sensor->dev, config->chan,
			SENSOR_ATTR_SAMPLING_FREQUENCY, &odr);
	if (ret) {
		LOG_ERR("%s set attr freq failed:%d", sensor->dev->name, ret);
		return ret;
	}

	if (sensor->interval) {
		if (config->is_streaming) {
			rtio_sqe_cancel(sensor->stream_sqe);
		} else {
			k_timer_stop(&sensor->timer);
		}
	}

	if (interval) {
		if (config->is_streaming) {
			ret = sensor_stream(sensor->iodev, &sensing_rtio_ctx,
					sensor, &sensor->stream_sqe);
		} else {
			k_timer_start(&sensor->timer, K_USEC(interval),
					K_USEC(interval));
		}
	}

	sensor->interval = interval;

	return ret;
}

static int config_interval(struct sensing_sensor *sensor)
{
	uint32_t interval = arbitrate_interval(sensor);

	LOG_INF("config interval, sensor:%s, interval:%d", sensor->dev->name, interval);

	return set_arbitrate_interval(sensor, interval);
}

static uint32_t arbitrate_sensitivity(struct sensing_sensor *sensor, int index)
{
	struct sensing_connection *conn;
	uint32_t min_sensitivity = UINT32_MAX;

	/* search from all clients, arbitrate the sensitivity */
	for_each_client_conn(sensor, conn) {
		LOG_DBG("arbitrate sensitivity, sensor:%s for each conn:%p, idx:%d, sens:%d",
				sensor->dev->name, conn, index,
				conn->sensitivity[index]);
		if (!is_client_request_data(conn)) {
			continue;
		}
		if (conn->sensitivity[index] < min_sensitivity) {
			min_sensitivity = conn->sensitivity[index];
		}
	}
	LOG_DBG("arbitrate sensitivity, sensor:%s, min_sensitivity:%d",
		sensor->dev->name, min_sensitivity);

	/* min_sensitivity == UINT32_MAX means no client is requesting to open sensor,
	 * by any client, in this case, return sensitivity 0
	 */
	return (min_sensitivity == UINT32_MAX ? 0 : min_sensitivity);
}

static int set_arbitrate_sensitivity(struct sensing_sensor *sensor, int index, uint32_t sensitivity)
{
	struct sensing_submit_config *config = (struct sensing_submit_config *)sensor->iodev->data;
	struct sensor_value threshold = {.val1 = sensitivity};
	int i;

	/* update sensor sensitivity */
	sensor->sensitivity[index] = sensitivity;

	for (i = 0; i < sensor->sensitivity_count; i++) {
		threshold.val1 = MIN(sensor->sensitivity[i], threshold.val1);
	}

	return sensor_attr_set(sensor->dev, config->chan,
			SENSOR_ATTR_HYSTERESIS, &threshold);
}

static int config_sensitivity(struct sensing_sensor *sensor, int index)
{
	uint32_t sensitivity = arbitrate_sensitivity(sensor, index);

	LOG_INF("config sensitivity, sensor:%s, index:%d, sensitivity:%d",
		sensor->dev->name, index, sensitivity);

	return set_arbitrate_sensitivity(sensor, index, sensitivity);
}

static int config_sensor(struct sensing_sensor *sensor)
{
	int ret;
	int i = 0;

	ret = config_interval(sensor);
	if (ret) {
		LOG_WRN("sensor:%s config interval error", sensor->dev->name);
	}

	for (i = 0; i < sensor->sensitivity_count; i++) {
		ret = config_sensitivity(sensor, i);
		if (ret) {
			LOG_WRN("sensor:%s config sensitivity index:%d error:%d",
					sensor->dev->name, i, ret);
		}
	}

	return ret;
}

static void sensor_later_config(void)
{
	LOG_INF("sensor later config begin...");

	for_each_sensor_reverse(sensor) {
		if (atomic_test_and_clear_bit(&sensor->flag, SENSOR_LATER_CFG_BIT)) {
			LOG_INF("sensor later config, sensor:%s",
				sensor->dev->name);
			config_sensor(sensor);
		}
	}
}

static void sensing_runtime_thread(void *p1, void *p2, void *p3)
{
	struct sensing_context *ctx = p1;
	int ret;

	LOG_INF("sensing runtime thread start...");

	do {
		ret = k_sem_take(&ctx->event_sem, K_FOREVER);
		if (!ret) {
			if (atomic_test_and_clear_bit(&ctx->event_flag, EVENT_CONFIG_READY)) {
				LOG_INF("runtime thread triggered by EVENT_CONFIG_READY");
				sensor_later_config();
			}
		}
	} while (1);
}

static void save_config_and_notify(struct sensing_sensor *sensor)
{
	struct sensing_context *ctx = &sensing_ctx;

	__ASSERT(sensor, "save config and notify, sensing_sensor not be NULL");

	LOG_INF("save config and notify, sensor:%s", sensor->dev->name);

	/* remember sensor_later_config bit to sensor */
	atomic_set_bit(&sensor->flag, SENSOR_LATER_CFG_BIT);

	/*remember event config ready and notify sensing_runtime_thread */
	atomic_set_bit(&ctx->event_flag, EVENT_CONFIG_READY);

	k_sem_give(&ctx->event_sem);
}

static int set_sensor_state(struct sensing_sensor *sensor, enum sensing_sensor_state state)
{
	__ASSERT(sensor, "set sensor state, sensing_sensor is NULL");

	sensor->state = state;

	return 0;
}

static void init_connection(struct sensing_connection *conn,
			    struct sensing_sensor *source,
			    struct sensing_sensor *sink)
{
	__ASSERT(conn, "init each connection, invalid connection");

	if (source) {
		conn->source = source;
	}

	if (sink) {
		conn->sink = sink;
	}

	conn->interval = 0;
	memset(conn->sensitivity, 0x00, sizeof(conn->sensitivity));
	/* link connection to its reporter's client_list */
	sys_slist_append(&conn->source->client_list, &conn->snode);
}

static void sensing_sensor_polling_timer(struct k_timer *timer_id)
{
	struct sensing_sensor *sensor = CONTAINER_OF(timer_id,
			struct sensing_sensor, timer);

	/* TODO: move it into sensing_runtime_thread */
	sensor_read(sensor->iodev, &sensing_rtio_ctx, sensor);
}

static int init_sensor(struct sensing_sensor *sensor)
{
	struct sensing_submit_config *config;
	struct sensing_connection *conn;
	int i;

	__ASSERT(sensor && sensor->dev, "init sensor, sensor or sensor device is NULL");

	k_timer_init(&sensor->timer, sensing_sensor_polling_timer, NULL);
	sys_slist_init(&sensor->client_list);

	for (i = 0; i < sensor->reporter_num; i++) {
		conn = &sensor->conns[i];

		/* source sensor has been assigned in compile time */
		init_connection(conn, NULL, sensor);

		LOG_INF("init sensor, reporter:%s, client:%s, connection:%d(%p)",
			conn->source->dev->name, sensor->dev->name, i, conn);
	}

	config = sensor->iodev->data;
	config->chan = sensing_sensor_type_to_chan(sensor->info->type);

	return 0;
}

static int sensing_init(const struct device *dev)
{
	struct sensing_context *ctx = dev->data;
	enum sensing_sensor_state state;
	int ret = 0;

	LOG_INF("sensing init begin...");

	for_each_sensor(sensor) {
		ret = init_sensor(sensor);
		if (ret) {
			LOG_ERR("sensor:%s initial error", sensor->dev->name);
		}
		state = (ret ? SENSING_SENSOR_STATE_OFFLINE : SENSING_SENSOR_STATE_READY);
		ret = set_sensor_state(sensor, state);
		if (ret) {
			LOG_ERR("set sensor:%s state:%d error", sensor->dev->name, state);
		}
		LOG_INF("sensing init, sensor:%s, state:%d", sensor->dev->name, sensor->state);
	}

	k_sem_init(&ctx->event_sem, 0, 1);

	LOG_INF("create sensing runtime thread ok");
	ctx->sensing_initialized = true;

	return ret;
}

int open_sensor(struct sensing_sensor *sensor, struct sensing_connection **conn)
{
	struct sensing_connection *tmp_conn;

	if (sensor->state != SENSING_SENSOR_STATE_READY) {
		return -EINVAL;
	}

	/* create connection from sensor to application(client = NULL) */
	tmp_conn = malloc(sizeof(*tmp_conn));
	if (!tmp_conn) {
		return -ENOMEM;
	}

	init_connection(tmp_conn, sensor, NULL);

	*conn = tmp_conn;

	return 0;
}

int close_sensor(struct sensing_connection **conn)
{
	struct sensing_connection *tmp_conn = *conn;

	if (tmp_conn == NULL) {
		LOG_ERR("connection should not be NULL");
		return -EINVAL;
	}

	__ASSERT(!tmp_conn->sink, "sensor derived from device tree cannot be closed");

	__ASSERT(tmp_conn->source, "reporter should not be NULL");

	sys_slist_find_and_remove(&tmp_conn->source->client_list, &tmp_conn->snode);

	save_config_and_notify(tmp_conn->source);

	free(*conn);
	*conn = NULL;

	return 0;
}

int sensing_register_callback(struct sensing_connection *conn,
			      struct sensing_callback_list *cb_list)
{
	if (conn == NULL) {
		LOG_ERR("register sensing callback list, connection not be NULL");
		return -ENODEV;
	}

	__ASSERT(!conn->sink, "only connection to application could register sensing callback");

	if (cb_list == NULL) {
		LOG_ERR("callback should not be NULL");
		return -ENODEV;
	}
	conn->callback_list = cb_list;

	return 0;
}

int set_interval(struct sensing_connection *conn, uint32_t interval)
{
	LOG_INF("set interval, sensor:%s, interval:%u(us)", conn->source->dev->name, interval);

	__ASSERT(conn && conn->source, "set interval, connection or reporter not be NULL");

	if (interval > 0 && interval < conn->source->info->minimal_interval) {
		LOG_ERR("interval:%d(us) should no less than min interval:%d(us)",
					interval, conn->source->info->minimal_interval);
		return -EINVAL;
	}

	conn->interval = interval;
	conn->next_consume_time = EXEC_TIME_INIT;

	LOG_INF("set interval, sensor:%s, conn:%p, interval:%d",
		conn->source->dev->name, conn, interval);

	save_config_and_notify(conn->source);

	return 0;
}

int get_interval(struct sensing_connection *conn, uint32_t *interval)
{
	__ASSERT(conn, "get interval, connection not be NULL");
	*interval = conn->interval;

	LOG_INF("get interval, sensor:%s, interval:%u(us)", conn->source->dev->name, *interval);

	return 0;
}

int set_sensitivity(struct sensing_connection *conn, int8_t index, uint32_t sensitivity)
{
	int i;

	__ASSERT(conn && conn->source, "set sensitivity, connection or reporter not be NULL");

	LOG_INF("set sensitivity, sensor:%s, index:%d, sensitivity:%d, count:%d",
		conn->source->dev->name, index,
		sensitivity, conn->source->sensitivity_count);

	if (index < SENSING_SENSITIVITY_INDEX_ALL || index >= conn->source->sensitivity_count) {
		LOG_ERR("sensor:%s sensitivity index:%d invalid", conn->source->dev->name, index);
		return -EINVAL;
	}

	if (index == SENSING_SENSITIVITY_INDEX_ALL) {
		for (i = 0; i < conn->source->sensitivity_count; i++) {
			conn->sensitivity[i] = sensitivity;
		}
	} else {
		conn->sensitivity[index] = sensitivity;
	}

	return 0;
}

int get_sensitivity(struct sensing_connection *conn, int8_t index, uint32_t *sensitivity)
{
	int i = 0;

	__ASSERT(conn && conn->source, "get sensitivity, connection or reporter not be NULL");

	*sensitivity = UINT32_MAX;

	if (index < SENSING_SENSITIVITY_INDEX_ALL || index >= conn->source->sensitivity_count) {
		LOG_ERR("sensor:%s sensitivity index:%d invalid", conn->source->dev->name, index);
		return -EINVAL;
	}

	if (index == SENSING_SENSITIVITY_INDEX_ALL) {
		/* each sensitivity index value should be same for global sensitivity */
		for (i = 1; i < conn->source->sensitivity_count; i++) {
			if (conn->sensitivity[i] != conn->sensitivity[0]) {
				LOG_ERR("sensitivity[%d]:%d should be same as sensitivity:%d",
					i, conn->sensitivity[i], conn->sensitivity[0]);
				return -EINVAL;
			}
		}
		*sensitivity = conn->sensitivity[0];
	} else {
		*sensitivity = conn->sensitivity[index];
	}

	LOG_INF("get_sensitivity, sensor:%s, index:%d, sensitivity:%d, count:%d",
		conn->source->dev->name, index,
		*sensitivity, conn->source->sensitivity_count);

	return 0;
}

int sensing_get_sensors(int *sensor_nums, const struct sensing_sensor_info **info)
{
	if (info == NULL) {
		LOG_ERR("sensing_sensor_info should not be NULL");
		return -ENODEV;
	}

	STRUCT_SECTION_COUNT(sensing_sensor_info, sensor_nums);

	STRUCT_SECTION_GET(sensing_sensor_info, 0, info);

	return 0;
}

K_THREAD_DEFINE(sensing_runtime, CONFIG_SENSING_RUNTIME_THREAD_STACK_SIZE, sensing_runtime_thread,
		&sensing_ctx, NULL, NULL, CONFIG_SENSING_RUNTIME_THREAD_PRIORITY, 0, 0);

DEVICE_DT_INST_DEFINE(0, sensing_init, NULL, &sensing_ctx, NULL, POST_KERNEL,
		      CONFIG_SENSOR_INIT_PRIORITY, NULL);
