/*
 * Copyright (c) 2021 Leica Geosystems AG
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#define DT_DRV_COMPAT sbs_sbs_gauge

#include <zephyr/drivers/i2c.h>
#include <zephyr/drivers/sensor.h>
#include <zephyr/sys/byteorder.h>

#include "sbs_gauge.h"

#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(sbs_gauge, CONFIG_SENSOR_LOG_LEVEL);

static int sbs_cmd_reg_read(const struct device *dev,
			    uint8_t reg_addr,
			    uint16_t *val)
{
	const struct sbs_gauge_config *cfg;
	uint8_t i2c_data[2];
	int status;

	cfg = dev->config;
	status = i2c_burst_read_dt(&cfg->i2c, reg_addr, i2c_data,
				   ARRAY_SIZE(i2c_data));
	if (status < 0) {
		LOG_ERR("Unable to read register");
		return status;
	}

	*val = sys_get_le16(i2c_data);

	return 0;
}

/**
 * @brief sensor value get
 *
 * @return -ENOTSUP for unsupported channels
 */
static int sbs_gauge_channel_get(const struct device *dev,
				 enum sensor_channel chan,
				 struct sensor_value *val)
{
	struct sbs_gauge_data *data;
	int32_t int_temp;

	data = dev->data;
	val->val2 = 0;

	switch (chan) {
	case SENSOR_CHAN_GAUGE_VOLTAGE:
		val->val1 = data->voltage / 1000;
		val->val2 = (data->voltage % 1000) * 1000;
		break;

	case SENSOR_CHAN_GAUGE_AVG_CURRENT:
		val->val1 = data->avg_current / 1000;
		val->val2 = (data->avg_current % 1000) * 1000;
		break;

	case SENSOR_CHAN_GAUGE_TEMP:
		int_temp = (data->internal_temperature * 10);
		int_temp = int_temp - 27315;
		val->val1 = int_temp / 100;
		val->val2 = (int_temp % 100) * 1000000;
		break;

	case SENSOR_CHAN_GAUGE_STATE_OF_CHARGE:
		val->val1 = data->state_of_charge;
		break;

	case SENSOR_CHAN_GAUGE_FULL_CHARGE_CAPACITY:
		val->val1 = data->full_charge_capacity;
		break;

	case SENSOR_CHAN_GAUGE_REMAINING_CHARGE_CAPACITY:
		val->val1 = data->remaining_charge_capacity;
		break;

	case SENSOR_CHAN_GAUGE_NOM_AVAIL_CAPACITY:
		val->val1 = data->nom_avail_capacity;
		break;

	case SENSOR_CHAN_GAUGE_FULL_AVAIL_CAPACITY:
		val->val1 = data->full_avail_capacity;
		break;

	case SENSOR_CHAN_GAUGE_TIME_TO_EMPTY:
		val->val1 = data->time_to_empty;
		break;

	case SENSOR_CHAN_GAUGE_TIME_TO_FULL:
		val->val1 = data->time_to_full;
		break;

	case SENSOR_CHAN_GAUGE_CYCLE_COUNT:
		val->val1 = data->cycle_count;
		break;

	default:
		return -ENOTSUP;
	}

	return 0;
}

static const uint16_t all_channels[] = {
	SENSOR_CHAN_GAUGE_VOLTAGE,
	SENSOR_CHAN_GAUGE_AVG_CURRENT,
	SENSOR_CHAN_GAUGE_TEMP,
	SENSOR_CHAN_GAUGE_STATE_OF_CHARGE,
	SENSOR_CHAN_GAUGE_FULL_CHARGE_CAPACITY,
	SENSOR_CHAN_GAUGE_REMAINING_CHARGE_CAPACITY,
	SENSOR_CHAN_GAUGE_NOM_AVAIL_CAPACITY,
	SENSOR_CHAN_GAUGE_FULL_AVAIL_CAPACITY,
	SENSOR_CHAN_GAUGE_TIME_TO_EMPTY,
	SENSOR_CHAN_GAUGE_TIME_TO_FULL,
	SENSOR_CHAN_GAUGE_CYCLE_COUNT
};

static int sbs_gauge_sample_fetch(const struct device *dev,
			    enum sensor_channel chan)
{
	struct sbs_gauge_data *data;
	int status = 0;

	data = dev->data;

	switch (chan) {
	case SENSOR_CHAN_GAUGE_VOLTAGE:
		status = sbs_cmd_reg_read(dev,
					  SBS_GAUGE_CMD_VOLTAGE,
					  &data->voltage);
		if (status < 0) {
			LOG_ERR("Failed to read voltage");
		}
		break;

	case SENSOR_CHAN_GAUGE_AVG_CURRENT:
		status = sbs_cmd_reg_read(dev,
					  SBS_GAUGE_CMD_AVG_CURRENT,
					  &data->avg_current);
		if (status < 0) {
			LOG_ERR("Failed to read average current ");
		}
		break;

	case SENSOR_CHAN_GAUGE_TEMP:
		status = sbs_cmd_reg_read(dev,
					  SBS_GAUGE_CMD_TEMP,
					  &data->internal_temperature);
		if (status < 0) {
			LOG_ERR("Failed to read internal temperature");
		}
		break;

	case SENSOR_CHAN_GAUGE_STATE_OF_CHARGE:
		status = sbs_cmd_reg_read(dev,
					  SBS_GAUGE_CMD_ASOC,
					  &data->state_of_charge);
		if (status < 0) {
			LOG_ERR("Failed to read state of charge");
		}
		break;

	case SENSOR_CHAN_GAUGE_FULL_CHARGE_CAPACITY:
		status = sbs_cmd_reg_read(dev,
					  SBS_GAUGE_CMD_FULL_CAPACITY,
					  &data->full_charge_capacity);
		if (status < 0) {
			LOG_ERR("Failed to read full charge capacity");
		}
		break;

	case SENSOR_CHAN_GAUGE_REMAINING_CHARGE_CAPACITY:
		status = sbs_cmd_reg_read(dev,
					  SBS_GAUGE_CMD_REM_CAPACITY,
					  &data->remaining_charge_capacity);
		if (status < 0) {
			LOG_ERR("Failed to read remaining charge capacity");
		}
		break;

	case SENSOR_CHAN_GAUGE_NOM_AVAIL_CAPACITY:
		status = sbs_cmd_reg_read(dev,
					  SBS_GAUGE_CMD_NOM_CAPACITY,
					  &data->nom_avail_capacity);
		if (status < 0) {
			LOG_ERR("Failed to read nominal available capacity");
		}
		break;

	case SENSOR_CHAN_GAUGE_FULL_AVAIL_CAPACITY:
		status = sbs_cmd_reg_read(dev,
					  SBS_GAUGE_CMD_FULL_CAPACITY,
					  &data->full_avail_capacity);
		if (status < 0) {
			LOG_ERR("Failed to read full available capacity");
		}
		break;

	case SENSOR_CHAN_GAUGE_TIME_TO_EMPTY:
		status = sbs_cmd_reg_read(dev,
					  SBS_GAUGE_CMD_AVG_TIME2EMPTY,
					  &data->time_to_empty);
		data->time_to_empty = (data->time_to_empty) & 0x00FF;

		if (status < 0) {
			LOG_ERR("Failed to read time to empty");
		}
		break;

	case SENSOR_CHAN_GAUGE_TIME_TO_FULL:
		status = sbs_cmd_reg_read(dev,
					  SBS_GAUGE_CMD_AVG_TIME2FULL,
					  &data->time_to_full);
		data->time_to_full = (data->time_to_full) & 0x00FF;

		if (status < 0) {
			LOG_ERR("Failed to read time to full");
		}
		break;

	case SENSOR_CHAN_GAUGE_CYCLE_COUNT:
		status = sbs_cmd_reg_read(dev,
					  SBS_GAUGE_CMD_CYCLE_COUNT,
					  &data->cycle_count);
		data->cycle_count = (data->cycle_count) & 0x00FF;

		if (status < 0) {
			LOG_ERR("Failed to read cycle count");
		}
		break;

	case SENSOR_CHAN_ALL:
		for (int i = 0; i < ARRAY_SIZE(all_channels); i++) {
			status = sbs_gauge_sample_fetch(dev, all_channels[i]);
			if (status != 0) {
				break;
			}
		}

		break;

	default:
		return -ENOTSUP;
	}

	return status;
}

/**
 * @brief initialize the fuel gauge
 *
 * @return 0 for success
 */
static int sbs_gauge_init(const struct device *dev)
{
	const struct sbs_gauge_config *cfg;

	cfg = dev->config;

	if (!device_is_ready(cfg->i2c.bus)) {
		LOG_ERR("Bus device is not ready");
		return -ENODEV;
	}

	return 0;
}

static const struct sensor_driver_api sbs_gauge_driver_api = {
	.sample_fetch = sbs_gauge_sample_fetch,
	.channel_get = sbs_gauge_channel_get,
};

#define SBS_GAUGE_INIT(index) \
	static struct sbs_gauge_data sbs_gauge_driver_##index; \
\
	static const struct sbs_gauge_config sbs_gauge_config_##index = { \
		.i2c = I2C_DT_SPEC_INST_GET(index), \
	}; \
\
	DEVICE_DT_INST_DEFINE(index, \
			    &sbs_gauge_init, \
			    NULL, \
			    &sbs_gauge_driver_##index, \
			    &sbs_gauge_config_##index, POST_KERNEL, \
			    CONFIG_SENSOR_INIT_PRIORITY, \
			    &sbs_gauge_driver_api);

DT_INST_FOREACH_STATUS_OKAY(SBS_GAUGE_INIT)
