#include <inttypes.h>
#include <stdlib.h> // for NULL

#include "lights.h"

static unsigned char on_pattern[] = {
	/* 8 bits */
	0b11111111,
};

#define IVA

static unsigned char blink_pattern[] = {
#ifdef IVA
	/* ../...-/..-/.../-.-/.-// */
	/* 137 bits, 19.7% on */
	0b10000100,
	0b00000000,
	0b10000100,
	0b00100001,
	0b11000000,
	0b00001000,
	0b01000011,
	0b10000000,
	0b00010000,
	0b10000100,
	0b00000000,
	0b11100001,
	0b00001110,
	0b00000000,
	0b01000011,
	0b10000000,
	0b00000000,
	0b00000000,
#else /* FILIP */
	/* ..-./../.-../../.--.// */
	/* 124 bits, 19.4% on */
	0b10000100,
	0b00111000,
	0b01000000,
	0b00001000,
	0b01000000,
	0b00001000,
	0b01110000,
	0b10000100,
	0b00000000,
	0b10000100,
	0b00000000,
	0b10000111,
	0b00001110,
	0b00010000,
	0b00000000,
	0b00000000,
#endif
};

static unsigned char slow_pattern[] = {
	/* 24 bits */
	0b00010000,
	0b00000000,
	0b00000000,
};

static unsigned char light_mode;
static union {
	unsigned char errors;
	struct {
		unsigned char shutdown_in_progress : 1;
		unsigned char pwmled_error : 1;
		unsigned char battery_low : 1;
	};
} e;

void set_error(unsigned char err)
{
	switch(err) {
	case ERR_BATTERY:
		e.battery_low = 1;
		pwmled_set_target(0);
		pattern_reload();
		break;
	case ERR_PWMLED:
		e.pwmled_error = 1;
		break;
	}
}

void init_control()
{
	light_mode = 1;
	e.errors = 0;
	short_press();
}

void long_press_start()
{
	e.shutdown_in_progress = 1;
	pattern_reload();
}

void short_press()
{
	if (e.battery_low)
		return;

	if (++light_mode >= 2*N_PWMLED_MODES)
		light_mode = 0;

	pwmled_set_target(light_mode < N_PWMLED_MODES
		? light_mode
		: light_mode - N_PWMLED_MODES);
	pattern_reload();
}

void long_press()
{
	power_down();
}

void pwmled_pattern_select(unsigned char led)
{
	if (e.shutdown_in_progress) {
		led_set_pattern(led, 0, 0, NULL);
	} else if (e.battery_low) {
		led_set_pattern(led, 24, 0, slow_pattern);
	} else if (light_mode == 0) {
		led_set_pattern(led, 24, 0, slow_pattern);
	} else if (light_mode < N_PWMLED_MODES) {
#ifdef IVA
		led_set_pattern(led, 137, 0, blink_pattern);
#else /* FILIP */
		led_set_pattern(led, 124, 0, blink_pattern);
#endif
	} else {
		led_set_pattern(led, 8, 0, on_pattern);
	}
}

void status_led_pattern_select(unsigned char led)
{
	if (e.shutdown_in_progress) {
		led_set_pattern(led, 8, 0, on_pattern);
	} else if (e.pwmled_error) {
		led_set_number_pattern(led, 1, 1);
	} else if (e.battery_low) {
		led_set_number_pattern(led, 1, 1);
	} else {
		led_set_number_pattern(led, battery_gauge(), 0);
	}
}

#if 0
void brake_on()
{
	braking = 1;
	gpio_set(0, 1);
	led_set_pattern(N_PWMLEDS, status_led_pattern_select());
	led_set_pattern(0, pwmled0_pattern_select());
}

void brake_off()
{
	braking = 0;
	gpio_set(0, 0);
	led_set_pattern(N_PWMLEDS, status_led_pattern_select());
	led_set_pattern(0, pwmled0_pattern_select());
}

#endif
