/*
 * Copyright (c) 2021 Titouan Christophe
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <zephyr/zephyr.h>
#include <zephyr/device.h>
#include <zephyr/drivers/sensor.h>
#include <zephyr/drivers/gpio.h>

#include "display_7seg.h"

/*
 * Get button configuration from the devicetree sw0 alias. This is mandatory.
 */
#define SW0_NODE        DT_ALIAS(sw0)
#if !DT_NODE_HAS_STATUS(SW0_NODE, okay)
#error "Unsupported board: sw0 devicetree alias is not defined"
#endif

#define N_MODES ARRAY_SIZE(modes)
#define N_SENSORS ARRAY_SIZE(sensors)
#define LEFT   sensors[0]
#define CENTER sensors[1]
#define RIGHT  sensors[2]

typedef void (*fsm_state)(void);

static int64_t last_mode_change;

static const struct device *sensors[] = {
	DEVICE_DT_GET(DT_NODELABEL(vl53l0x_l)),
	DEVICE_DT_GET(DT_NODELABEL(vl53l0x_c)),
	DEVICE_DT_GET(DT_NODELABEL(vl53l0x_r)),
};

static void mode_show_distance(void)
{
	int ret;
	double distance;
	struct sensor_value value;

	ret = sensor_sample_fetch(CENTER);
	if (ret) {
		printk("sensor_sample_fetch(%s) failed -> %d\n", CENTER->name, ret);
		display_chars(TEXT_Err);
		return;
	}

	ret = sensor_channel_get(CENTER, SENSOR_CHAN_DISTANCE, &value);
	if (ret) {
		printk("sensor_channel_get(%s) failed -> %d\n", CENTER->name, ret);
		display_chars(TEXT_Err);
		return;
	}
	distance = sensor_value_to_double(&value);
	if (distance < 1.25) {
		display_number(100 * distance, 10);
	} else {
		display_chars(DISPLAY_OFF);
	}
}

static void mode_show_presence(void)
{
	int i, ret;
	struct sensor_value value;
	uint8_t text[4] = { CHAR_OFF, CHAR_OFF, CHAR_OFF, CHAR_OFF };

	for (i = 0; i < N_SENSORS; i++) {
		ret = sensor_sample_fetch(sensors[i]);
		if (ret) {
			printk("sensor_sample_fetch(%s) failed -> %d\n",
			       sensors[i]->name, ret);
			display_chars(TEXT_Err);
			return;
		}
		ret = sensor_channel_get(sensors[i],
					 SENSOR_CHAN_PROX,
					 &value);
		if (ret) {
			printk("sensor_channel_get(%s) failed -> %d\n",
			       sensors[i]->name, ret);
			display_chars(TEXT_Err);
			return;
		}

		if (value.val1) {
			text[i] = CHAR_UNDERSCORE | CHAR_DASH | CHAR_OVERLINE;
		}
	}
	display_chars(text);
}

static size_t current_mode;
static fsm_state modes[] = {
	mode_show_distance,
	mode_show_presence,
};

static void change_mode(const struct device *dev, struct gpio_callback *cb, uint32_t pins)
{
	(void) dev;
	(void) cb;
	(void) pins;

	int64_t now = k_uptime_get();

	if (now - last_mode_change > 300) {
		current_mode = (current_mode + 1) % N_MODES;
		last_mode_change = now;
	}
}


void main(void)
{
	struct gpio_callback button_cb_data;
	const uint8_t Hello[4] = { CHAR_H, CHAR_E, CHAR_PIPE | CHAR_1, CHAR_0 };
	const struct gpio_dt_spec button = GPIO_DT_SPEC_GET(SW0_NODE, gpios);

	display_chars(Hello);
	k_sleep(K_MSEC(1000));

	if (!device_is_ready(button.port)) {
		printk("Error: button device %s is not ready\n",
		       button.port->name);
		return;
	}

	gpio_pin_configure_dt(&button, GPIO_INPUT);
	gpio_pin_interrupt_configure_dt(&button, GPIO_INT_EDGE_RISING);
	gpio_init_callback(&button_cb_data, change_mode, BIT(button.pin));
	gpio_add_callback(button.port, &button_cb_data);

	while (1) {
		modes[current_mode]();
	}
}
