/*
 * Copyright (c) 2020 Richard Osterloh
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include "vcnl4040.h"
#include <zephyr/logging/log.h>

LOG_MODULE_DECLARE(vcnl4040, CONFIG_SENSOR_LOG_LEVEL);

static void vcnl4040_handle_cb(struct vcnl4040_data *data)
{
	const struct vcnl4040_config *config = data->dev->config;

	gpio_pin_interrupt_configure_dt(&config->int_gpio, GPIO_INT_DISABLE);

#if defined(CONFIG_VCNL4040_TRIGGER_OWN_THREAD)
	k_sem_give(&data->trig_sem);
#elif defined(CONFIG_VCNL4040_TRIGGER_GLOBAL_THREAD)
	k_work_submit(&data->work);
#endif
}

static void vcnl4040_gpio_callback(const struct device *dev,
				   struct gpio_callback *cb,
				   uint32_t pin_mask)
{
	struct vcnl4040_data *data =
		CONTAINER_OF(cb, struct vcnl4040_data, gpio_cb);
	const struct vcnl4040_config *config = data->dev->config;

	if ((pin_mask & BIT(config->int_gpio.pin)) == 0U) {
		return;
	}

	vcnl4040_handle_cb(data);
}

static int vcnl4040_handle_proxy_int(const struct device *dev)
{
	struct vcnl4040_data *data = dev->data;
	struct sensor_trigger proxy_trig = {
		.type = SENSOR_TRIG_THRESHOLD,
		.chan = SENSOR_CHAN_PROX,
	};

	if (data->proxy_handler) {
		data->proxy_handler(dev, &proxy_trig);
	}

	return 0;
}

static int vcnl4040_handle_als_int(const struct device *dev)
{
	struct vcnl4040_data *data = dev->data;
	struct sensor_trigger als_trig = {
		.type = SENSOR_TRIG_THRESHOLD,
		.chan = SENSOR_CHAN_LIGHT,
	};

	if (data->als_handler) {
		data->als_handler(dev, &als_trig);
	}

	return 0;
}

static void vcnl4040_handle_int(const struct device *dev)
{
	const struct vcnl4040_config *config = dev->config;
	struct vcnl4040_data *data = dev->data;
	uint16_t int_source;

	k_sem_take(&data->sem, K_FOREVER);

	if (vcnl4040_read(dev, VCNL4040_REG_INT_FLAG, &int_source)) {
		LOG_ERR("Could not read interrupt source");
		int_source = 0U;
	}

	k_sem_give(&data->sem);

	data->int_type = int_source >> 8;

	if (data->int_type == VCNL4040_PROXIMITY_AWAY ||
	    data->int_type == VCNL4040_PROXIMITY_CLOSE) {
		vcnl4040_handle_proxy_int(dev);
	} else if (data->int_type == VCNL4040_AMBIENT_HIGH ||
		   data->int_type == VCNL4040_AMBIENT_LOW) {
		vcnl4040_handle_als_int(dev);
	} else {
		LOG_ERR("Unknown interrupt source %d", data->int_type);
	}

	gpio_pin_interrupt_configure_dt(&config->int_gpio, GPIO_INT_EDGE_TO_ACTIVE);
}

#ifdef CONFIG_VCNL4040_TRIGGER_OWN_THREAD
static void vcnl4040_thread_main(struct vcnl4040_data *data)
{
	while (true) {
		k_sem_take(&data->trig_sem, K_FOREVER);
		vcnl4040_handle_int(data->dev);
	}
}
#endif

#ifdef CONFIG_VCNL4040_TRIGGER_GLOBAL_THREAD
static void vcnl4040_work_handler(struct k_work *work)
{
	struct vcnl4040_data *data =
		CONTAINER_OF(work, struct vcnl4040_data, work);

	vcnl4040_handle_int(data->dev);
}
#endif

int vcnl4040_attr_set(const struct device *dev,
		      enum sensor_channel chan,
		      enum sensor_attribute attr,
		      const struct sensor_value *val)
{
	struct vcnl4040_data *data = dev->data;
	const struct vcnl4040_config *config = dev->config;
	int ret = 0;

	if (!config->int_gpio.port) {
		return -ENOTSUP;
	}

	k_sem_take(&data->sem, K_FOREVER);

	if (chan == SENSOR_CHAN_PROX) {
		if (attr == SENSOR_ATTR_UPPER_THRESH) {
			if (vcnl4040_write(dev, VCNL4040_REG_PS_THDH,
					   (uint16_t)val->val1)) {
				ret = -EIO;
				goto exit;
			}

			ret = 0;
			goto exit;
		}
		if (attr == SENSOR_ATTR_LOWER_THRESH) {
			if (vcnl4040_write(dev, VCNL4040_REG_PS_THDL,
					   (uint16_t)val->val1)) {
				ret = -EIO;
				goto exit;
			}

			ret = 0;
			goto exit;
		}
	}
#ifdef CONFIG_VCNL4040_ENABLE_ALS
	if (chan == SENSOR_CHAN_LIGHT) {
		if (attr == SENSOR_ATTR_UPPER_THRESH) {
			if (vcnl4040_write(dev, VCNL4040_REG_ALS_THDH,
					   (uint16_t)val->val1)) {
				ret = -EIO;
				goto exit;
			}

			ret = 0;
			goto exit;
		}
		if (attr == SENSOR_ATTR_LOWER_THRESH) {
			if (vcnl4040_write(dev, VCNL4040_REG_ALS_THDL,
					   (uint16_t)val->val1)) {
				ret = -EIO;
				goto exit;
			}

			ret = 0;
			goto exit;
		}
	}
#endif
	ret = -ENOTSUP;
exit:
	k_sem_give(&data->sem);

	return ret;
}

int vcnl4040_trigger_set(const struct device *dev,
			 const struct sensor_trigger *trig,
			 sensor_trigger_handler_t handler)
{
	const struct vcnl4040_config *config = dev->config;
	struct vcnl4040_data *data = dev->data;
	uint16_t conf;
	int ret = 0;

	if (!config->int_gpio.port) {
		return -ENOTSUP;
	}

	k_sem_take(&data->sem, K_FOREVER);

	switch (trig->type) {
	case SENSOR_TRIG_THRESHOLD:
		if (trig->chan == SENSOR_CHAN_PROX) {
			if (vcnl4040_read(dev, VCNL4040_REG_PS_CONF, &conf)) {
				ret = -EIO;
				goto exit;
			}

			/* Set interrupt bits 1:0 of high register */
			conf |= config->proxy_type << 8;

			if (vcnl4040_write(dev, VCNL4040_REG_PS_CONF, conf)) {
				ret = -EIO;
				goto exit;
			}

			data->proxy_handler = handler;
		} else if (trig->chan == SENSOR_CHAN_LIGHT) {
#ifdef CONFIG_VCNL4040_ENABLE_ALS
			if (vcnl4040_read(dev, VCNL4040_REG_ALS_CONF, &conf)) {
				ret = -EIO;
				goto exit;
			}

			/* Set interrupt enable bit 1 */
			conf |= 1 << 1;

			if (vcnl4040_write(dev, VCNL4040_REG_ALS_CONF, conf)) {
				ret = -EIO;
				goto exit;
			}

			data->als_handler = handler;
#else
			ret = -ENOTSUP;
			goto exit;
#endif
		} else {
			ret = -ENOTSUP;
			goto exit;
		}
		break;
	default:
		LOG_ERR("Unsupported sensor trigger");
		ret = -ENOTSUP;
		goto exit;
	}
exit:
	k_sem_give(&data->sem);

	return ret;
}

int vcnl4040_trigger_init(const struct device *dev)
{
	const struct vcnl4040_config *config = dev->config;
	struct vcnl4040_data *data = dev->data;

	data->dev = dev;

	/* dts doesn't have GPIO int pin set, so we dont support
	 * trigger mode for this instance
	 */
	if (!config->int_gpio.port) {
		return 0;
	}

	/* Get the GPIO device */
	if (!device_is_ready(config->int_gpio.port)) {
		LOG_ERR("%s: device %s is not ready", dev->name,
				config->int_gpio.port->name);
		return -ENODEV;
	}

#if defined(CONFIG_VCNL4040_TRIGGER_OWN_THREAD)
	k_sem_init(&data->trig_sem, 0, K_SEM_MAX_LIMIT);
	k_thread_create(&data->thread, data->thread_stack,
			CONFIG_VCNL4040_THREAD_STACK_SIZE,
			(k_thread_entry_t)vcnl4040_thread_main,
			data, NULL, NULL,
			K_PRIO_COOP(CONFIG_VCNL4040_THREAD_PRIORITY),
			0, K_NO_WAIT);
	k_thread_name_set(&data->thread, "VCNL4040 trigger");
#elif defined(CONFIG_VCNL4040_TRIGGER_GLOBAL_THREAD)
	data->work.handler = vcnl4040_work_handler;
#endif

	gpio_pin_configure_dt(&config->int_gpio, GPIO_INPUT);

	gpio_init_callback(&data->gpio_cb, vcnl4040_gpio_callback,
			   BIT(config->int_gpio.pin));

	if (gpio_add_callback(config->int_gpio.port, &data->gpio_cb) < 0) {
		LOG_DBG("Failed to set gpio callback!");
		return -EIO;
	}

	gpio_pin_interrupt_configure_dt(&config->int_gpio, GPIO_INT_EDGE_TO_ACTIVE);

	if (gpio_pin_get_dt(&config->int_gpio) > 0) {
		vcnl4040_handle_cb(data);
	}

	return 0;
}
