/*
 * Copyright (c) 2017 BayLibre, SAS
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <drivers/clock_control/stm32_clock_control.h>
#include <drivers/clock_control.h>
#include <sys/util.h>
#include <kernel.h>
#include <errno.h>
#include <drivers/i2c.h>

#define LOG_LEVEL CONFIG_I2C_LOG_LEVEL
#include <logging/log.h>
LOG_MODULE_DECLARE(main);

#define DEV_DATA(dev) ((struct i2c_virtual_data * const)(dev)->data)

struct i2c_virtual_data {
	sys_slist_t slaves;
};

int i2c_virtual_runtime_configure(const struct device *dev, uint32_t config)
{
	return 0;
}

static struct i2c_slave_config *find_address(struct i2c_virtual_data *data,
					     uint16_t address, bool is_10bit)
{
	struct i2c_slave_config *cfg = NULL;
	sys_snode_t *node;
	bool search_10bit;

	SYS_SLIST_FOR_EACH_NODE(&data->slaves, node) {
		cfg = CONTAINER_OF(node, struct i2c_slave_config, node);

		search_10bit = (cfg->flags & I2C_SLAVE_FLAGS_ADDR_10_BITS);

		if (cfg->address == address && search_10bit == is_10bit) {
			return cfg;
		}
	}

	return NULL;
}

/* Attach I2C slaves */
int i2c_virtual_slave_register(const struct device *dev,
			       struct i2c_slave_config *config)
{
	struct i2c_virtual_data *data = DEV_DATA(dev);

	if (!config) {
		return -EINVAL;
	}

	/* Check the address is unique */
	if (find_address(data, config->address,
			 (config->flags & I2C_SLAVE_FLAGS_ADDR_10_BITS))) {
		return -EINVAL;
	}

	sys_slist_append(&data->slaves, &config->node);

	return 0;
}


int i2c_virtual_slave_unregister(const struct device *dev,
				 struct i2c_slave_config *config)
{
	struct i2c_virtual_data *data = DEV_DATA(dev);

	if (!config) {
		return -EINVAL;
	}

	if (!sys_slist_find_and_remove(&data->slaves, &config->node)) {
		return -EINVAL;
	}

	return 0;
}

static int i2c_virtual_msg_write(const struct device *dev,
				 struct i2c_msg *msg,
				 struct i2c_slave_config *config,
				 bool prev_write)
{
	unsigned int len = 0U;
	uint8_t *buf = msg->buf;
	int ret;

	if (!prev_write) {
		config->callbacks->write_requested(config);
	}

	len = msg->len;
	while (len) {

		ret = config->callbacks->write_received(config, *buf);
		if (ret) {
			goto error;
		}
		buf++;
		len--;
	}

	if (!(msg->flags & I2C_MSG_RESTART) && msg->flags & I2C_MSG_STOP) {
		config->callbacks->stop(config);
	}

	return 0;
error:
	LOG_DBG("%s: NACK", __func__);

	return -EIO;
}

static int i2c_virtual_msg_read(const struct device *dev, struct i2c_msg *msg,
				struct i2c_slave_config *config)
{
	unsigned int len = msg->len;
	uint8_t *buf = msg->buf;

	if (!msg->len) {
		return 0;
	}

	config->callbacks->read_requested(config, buf);
	buf++;
	len--;

	while (len) {
		config->callbacks->read_processed(config, buf);
		buf++;
		len--;
	}

	if (!(msg->flags & I2C_MSG_RESTART) && msg->flags & I2C_MSG_STOP) {
		config->callbacks->stop(config);
	}

	return 0;
}

#define OPERATION(msg) (((struct i2c_msg *) msg)->flags & I2C_MSG_RW_MASK)

static int i2c_virtual_transfer(const struct device *dev, struct i2c_msg *msg,
				uint8_t num_msgs, uint16_t slave)
{
	struct i2c_virtual_data *data = DEV_DATA(dev);
	struct i2c_msg *current, *next;
	struct i2c_slave_config *cfg;
	bool is_write = false;
	int ret = 0;

	cfg = find_address(data, slave, (msg->flags & I2C_SLAVE_FLAGS_ADDR_10_BITS));
	if (!cfg) {
		return -EIO;
	}

	current = msg;
	current->flags |= I2C_MSG_RESTART;
	while (num_msgs > 0) {
		if (num_msgs > 1) {
			next = current + 1;

			/*
			 * Stop or restart condition between messages
			 * of different directions is required
			 */
			if (OPERATION(current) != OPERATION(next)) {
				if (!(next->flags & I2C_MSG_RESTART)) {
					ret = -EINVAL;
					break;
				}
			}
		}

		/* Stop condition is required for the last message */
		if ((num_msgs == 1U) && !(current->flags & I2C_MSG_STOP)) {
			ret = -EINVAL;
			break;
		}

		if ((current->flags & I2C_MSG_RW_MASK) == I2C_MSG_WRITE) {
			ret = i2c_virtual_msg_write(dev, current,
						    cfg, is_write);
			is_write = true;
		} else {
			ret = i2c_virtual_msg_read(dev, current, cfg);
			is_write = false;
		}

		if (ret < 0) {
			break;
		}

		current++;
		num_msgs--;
	}

	return ret;
}

static const struct i2c_driver_api api_funcs = {
	.configure = i2c_virtual_runtime_configure,
	.transfer = i2c_virtual_transfer,
	.slave_register = i2c_virtual_slave_register,
	.slave_unregister = i2c_virtual_slave_unregister,
};

static int i2c_virtual_init(const struct device *dev)
{
	struct i2c_virtual_data *data = DEV_DATA(dev);

	sys_slist_init(&data->slaves);

	return 0;
}

static struct i2c_virtual_data i2c_virtual_dev_data_0;

DEVICE_DEFINE(i2c_virtual_0, CONFIG_I2C_VIRTUAL_NAME, &i2c_virtual_init,
		NULL, &i2c_virtual_dev_data_0, NULL,
		POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE,
		&api_funcs);
