#include "openChargeMicro.h"

charger* chargers;
clock* clk;
gui* ui;
ioController* io;

void createChargers();
void printStatus();

bool everySec();

int indexCount = 0;

int main(void) {
#ifdef DEBUG
	serialSetup();
	serialSend("Hello World - ");
	serialSend(__DATE__ __TIME__);
	serialSend("\r\n");
#endif

	ui = (gui*) malloc(sizeof(gui));

	ui->gui_init();
#ifndef DEBUG
	_delay_ms(1000);
#endif
	ui->gui_info();

	io = (ioController*) malloc(sizeof(ioController));

	io->setBuzzer(false);
	io->deactivateChargers();
	io->setActiveLED(true);
	io->activateChargers();

	chargers = (charger *) malloc(CHARGER_SIZE * sizeof(charger));

	clk = (clock *) malloc(sizeof(clock));
	clock tmp;
	clk = &tmp;

	createChargers();

	//io.setWS2812(0, 255, 255);

	//loop till power off
	while (true) {
		updateGUI();
		checkForBattery();
	}

	return 0;
}

void updateGUI() {
	if (everySec()) { //updates the ui every sec
		bool next = true;
		bool notfound = true;
		static bool found = true;
		int loops = 0;

		//finds one or more active charges or aborts after CHARGER_SIZE
		while (next && (loops < CHARGER_SIZE)) {
			loops++;
			if (chargers[indexCount].getStatus().connected) {
#ifdef DEBUG
				char c[50];
				sprintf(c, "updating: %i\r\n", (int) indexCount);
				serialSend(c);
#endif
				ui->gui_print((indexCount + 1), true,
						clk->getTime(chargers[indexCount].getStartTime()),
						chargers[indexCount].getVoltage(),
						chargers[indexCount].getCurrent(),
						chargers[indexCount].getCapacity());
				notfound = false;
				next = false;
				found = true;
			}
			indexCount = (indexCount + 1) % CHARGER_SIZE;
		} //end while
		if (notfound && found) {
			ui->gui_info();
			found = false;
		}
	} //end everySec
}

bool everySec() {

	static uint32_t time;
	if (clk->getTime() != time) {
		time = clk->getTime();
		return true;
	}
	return false;
}

void updateChargers() {
	for (int i = 0; i < CHARGER_SIZE; i++) {
		if (chargers[i].getStatus().connected) {
			//charger active --> battery pluged on
			chargers[i].update();
		}
	}
}

void checkForBattery() {   		//TODO
	static int activeChargers[CHARGER_SIZE];
	static int errorCount[CHARGER_SIZE];

	for (int l = 0; l < CHARGER_SIZE; l++) {

		bool zero = false;
		double tmp1 = 0.0;
		double tmp2 = 0.0;
		double difference = 0.1;

		for (int i = 0; i < 8; i++) {
			tmp2 = tmp1;
			tmp1 = chargers[l].getVoltage();

#ifdef DEBUG
			//char x[50];
			// dtostrf(tmp1, 2, 2, x);
			//serialSend(x);
			//serialSend("\r\n");
#endif

			if ((tmp1 == 0.0)
					|| (((tmp1 - tmp2 > difference) || (tmp1 < 3.2)) && i != 0)) {
				zero = true;
			}
		}

		if (!zero) {
			struct s_charger_status tmp = chargers[l].getStatus();
			tmp.connected = true;
			chargers[l].setStatus(tmp);
			//io->setActiveLED(true);
			if (activeChargers[l] == 0) {
				chargers[l].setStartTime(clk->getTimeStamp());

#ifdef DEBUG
				serialSend("allowed\r\n");
#endif
			}
			activeChargers[l] = 1;
			errorCount[l] = CONNECTION_TIMEOUT;

		} else {
			//io->setActiveLED(false);

			errorCount[l]--;
#ifdef DEBUG
			serialSend("no connection\r\n");
#endif
			if (errorCount[l] == 0) {
				struct s_charger_status tmp = chargers[l].getStatus();
							tmp.connected = false;
							chargers[l].setStatus(tmp);
				activeChargers[l] = 0;
				chargers[l].reset(); //sets the capacity to zero
#ifdef DEBUG
				serialSend("blocked\r\n");
#endif
			}

		}
	}
}

void createChargers() {
	s_charger charger_settings;

	charger_settings.chU = CH0_U;
	charger_settings.chI = CH0_I;
	charger_settings.nr = CH0_NR;
	charger chrg0 = charger(charger_settings);
	chargers[0] = chrg0;

	charger_settings.chU = CH1_U;
	charger_settings.chI = CH1_I;
	charger_settings.nr = CH1_NR;
	charger chrg1 = charger(charger_settings);
	chargers[1] = chrg1;

	charger_settings.chU = CH2_U;
	charger_settings.chI = CH2_I;
	charger_settings.nr = CH2_NR;
	charger chrg2 = charger(charger_settings);
	chargers[2] = chrg2;

	charger_settings.chU = CH3_U;
	charger_settings.chI = CH3_I;
	charger_settings.nr = CH3_NR;
	charger chrg3 = charger(charger_settings);
	chargers[3] = chrg3;
}

void printStatus() {
	//serialSend("printing status .. \r\n");
	for (int i = 0; i < CHARGER_SIZE; i++) {
		if (chargers[i].getStatus().connected) {
			chargers[i].getInfo(); //print values
			//char charVal[10];
			//dtostrf(chargers[i].getCurrent(), 4, 0, charVal);
			//sprintf(charVal, "%i µAh\r\n", chargers[i].getCapacity());
			//serialSend(charVal);
			//serialSend(" mA\r\n");
		}
	}
}

#ifdef DEBUG

void serialSetup(void) {
	//Register settings
	//High and low bits
	UBRR0H = (BUAD_RATE_CALC >> 8);
	UBRR0L = BUAD_RATE_CALC;
	//transimit and recieve enable
	UCSR0B = (1 << TXEN0) | (1 << TXCIE0) | (1 << RXEN0) | (1 << RXCIE0);
	UCSR0C = (1 << UCSZ01) | (1 << UCSZ00);	//8 bit data format
}

void serialSend(const char* sendString) {
	for (unsigned int i = 0; i < strlen(sendString); i++) {
		while (( UCSR0A & (1 << UDRE0)) == 0) {
		};
		UDR0 = sendString[i];
	}
}

#endif
