#include "internal.h"

#include <string.h>
#include <exception>
#include <stdexcept>
#include <iostream>
#include <sstream>

using namespace std;

static LED *current_led;

std::vector<std::string> all_led_types()
{
	std::vector<std::string> res;

	for (unsigned int i = 0; i < num_led_types; i++) {
		struct led_type *def = led_types + i;

		res.push_back(def->name);
	}

	return res;
}

LED::LED(const std::string &type)
	: def(NULL)
{
	for (unsigned int i = 0; i < num_led_types; i++) {
		struct led_type *def = led_types + i;

		if (def->name == type) {
			this->def = def;
		}
	}

	if (!this->def) {
		throw runtime_error(std::string("Unknown type ") + type);
	}
}

LEDState LED::evaluate(const EventState &eventState)
{
	LEDState state;
	int i;
	led_overlay_t o;

	this->led.current_color.brightness = 0xFF;
	this->led.current_color.c[0] = 0xFF;
	this->led.current_color.c[1] = 0x00;
	this->led.current_color.c[2] = 0x00;
	this->led.options.location = 2;

	this->eventState = &eventState;
	current_led = this;

	for (i = 0, o = this->def->overlays[i]; o.func != NULL;
	     i++, o = this->def->overlays[i]) {
		state.code = o.func(&this->led);

		if (state.code.type != blink_invalid) {
			state.overlay_name = o.name;
			break;
		}
	}

	return state;
}

int LED::_event_get_value(const char *file, int line, const char *func,
			  struct event *event)
{
	return this->eventState->get(event);
}

int LED::_leds_max_location(const char *file, int line, const char *func)
{
	return 2;
}

bool LED::_leds_all_dimmable(const char *file, int line, const char *func)
{
	return false;
}

void LED::_led_set_current_color(struct led *led, enum led_color_name name)
{
	switch (name) {
	case led_color_name_normal:
		led->current_color.c[0] = 0xFF;
		led->current_color.c[1] = 0x00;
		led->current_color.c[2] = 0x00;
		break;
	case led_color_name_warn:
		led->current_color.c[0] = 0x00;
		led->current_color.c[1] = 0xFF;
		led->current_color.c[2] = 0x00;
		break;
	case led_color_name_error:
		led->current_color.c[0] = 0x00;
		led->current_color.c[1] = 0x00;
		led->current_color.c[2] = 0xFF;
		break;
	}
}

int _event_get_value(const char *file, int line, const char *func,
		     struct event *event)
{
	return current_led->_event_get_value(file, line, func, event);
}

int _leds_max_location(const char *file, int line, const char *func)
{
	return current_led->_leds_max_location(file, line, func);
}

bool _leds_all_dimmable(const char *file, int line, const char *func)
{
	return current_led->_leds_all_dimmable(file, line, func);
}

void _led_set_current_color(struct led *led, enum led_color_name name)
{
	current_led->_led_set_current_color(led, name);
}