/*
 * 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);

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;

	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;

	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;
	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;

	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);
