#include "microcontroller.h"

void Microcontroller::relayToggle(int state, int relay)
{
	char buffer[8];
	int length = sprintf(buffer, "%d \n", relay);
	state ? write("item on ") : write("item off ");
	write(buffer, length);
}

void Microcontroller::relayOn(int relay)
{
	relayToggle(true, relay);
}

void Microcontroller::relayOff(int relay)
{
	relayToggle(false, relay);
}

//rgb lights

void Microcontroller::rgbOn()
{
	write("rgb on\n");
}

void Microcontroller::rgbOff()
{
	write( "rgb off\n");
}

void Microcontroller::changeRgbColor(const QColor color)
{
	char buffer[64];
	int length = sprintf(buffer, "rgb set %03d %03d %03d\n", color.red(), color.green(), color.blue());
	write(buffer, length);
}

void Microcontroller::setAuxPwm(int duty)
{
	char buffer[64];
	int length = sprintf(buffer, "aux set %03d\n", duty );
	write(buffer, length);
}

void Microcontroller::write(const QByteArray& buffer)
{
	writeQue.enqueue(buffer);
	if(!writeTimer.isActive())
	{
		writeTimer.setInterval(0);
		writeTimer.start();
	}
}

void Microcontroller::write(char* buffer, const size_t length)
{
	write(QByteArray(buffer, length));
}

void Microcontroller::onWriteTimerTimeout()
{
	writeTimer.setInterval(50);
	if(connected())
	{
		if(!writeQue.empty())
		{
			QByteArray data = writeQue.dequeue();
			_port->write(data);
		}
		else
		{
			writeTimer.stop();
		}
	}
}

void Microcontroller::setPattern(int pattern)
{
	char buffer[4];
	write("rgb pattern ");
	int length = sprintf(buffer, "%d\n", pattern);
	write(buffer, length);
}

void Microcontroller::startSunrise()
{
	setPattern(4);
}

bool Microcontroller::connected()
{
	if(_port != nullptr)
		return _port->isOpen();
	else
		return false;
}

void Microcontroller::refresh()
{
	write("state\n");
}

//housekeeping

Microcontroller::Microcontroller(QIODevice* port): Microcontroller()
{
	setIODevice(port);
}

Microcontroller::Microcontroller()
{
	writeTimer.setInterval(50);
	writeTimer.setSingleShot(false);
	connect(&writeTimer, &QTimer::timeout, this, &Microcontroller::onWriteTimerTimeout);
	qDebug()<<__func__<<writeTimer.isActive();
}

Microcontroller::~Microcontroller()
{
}

void Microcontroller::setIODevice(QIODevice *port)
{
	_port = port;
	QObject::connect(_port, &QIODevice::readyRead, this, &Microcontroller::isReadyRead);
}

std::shared_ptr<Relay> Microcontroller::processRelayLine(const QString& buffer)
{
	QStringList bufferList = buffer.split(' ');
	if(bufferList.size() >= 9 && buffer.startsWith("ITEM NUMBER:"))
	{
		QString name;
		for(int i = 10; i < bufferList.size(); i++)
			name.append(bufferList[i] + ' ');
		if(name.size() > 1)
			name.remove(name.size()-1, 1);
		else
			name = "Relay " + QString::number(bufferList[1].toInt(nullptr, 2));
		return std::shared_ptr<Relay>(new Relay(bufferList[2].toInt(),
												name,
												bufferList[6].toInt(nullptr, 2),
												bufferList[8].toInt()));
	}
	return  nullptr;
}

void Microcontroller::processList(const QString& buffer)
{
	QStringList bufferList = buffer.split(' ');
	if(bufferList.size() >= 8 && buffer.startsWith("ITEM NUMBER:"))
	{
		relayList.push_back(processRelayLine(buffer));
	}
	else if(buffer.contains("EOL"))
	{
		listMode = false;
		std::vector<ItemAddRequest> requests;
		for(const std::shared_ptr<Item>& item : relayList)
		{
			ItemAddRequest request;
			request.changes.name = true;
			request.changes.value = true;
			request.payload = item;
			request.type = ITEM_UPDATE_BACKEND;
			requests.push_back(request);
		}
		gotItems(requests);
		relayList.clear();
	}
	else
	{
		listMode = false;
	}
}

void Microcontroller::processRelayState(const QString& buffer)
{
	ItemUpdateRequest update;
	update.type = ITEM_UPDATE_BACKEND;
	update.changes.name = true;
	update.changes.value = true;
	update.payload = static_cast<ItemData>(*processRelayLine(buffer));
	updateItems({update});
}

void Microcontroller::processSensorState(const QString& buffer)
{
	Sensor sensor = Sensor::sensorFromString(buffer);
	if(sensor.type != Sensor::TYPE_DUMMY)
		gotSensorState(sensor, SENSOR_UPDATE_BACKEND);
}


void Microcontroller::processMicroReturn()
{
	if(listMode)
	{
		processList(_buffer);
	}
	else
	{
		if(_buffer.startsWith("Items:"))
		{
			listMode = true;
			relayList.clear();
		}
		else if(_buffer.startsWith("ITEM NUMBER:"))
		{
			processRelayState(_buffer);
		}
		else if(_buffer.startsWith("SENSOR"))
		{
			processSensorState(_buffer);
		}
	}

}

void Microcontroller::isReadyRead()
{
	char charBuf;
	while(_port->getChar(&charBuf))
	{
		_buffer.push_back(charBuf);
		if(_buffer.endsWith('\n') )
		{
			_buffer.remove('\n');
			processMicroReturn();
			textRecived(_buffer);
			_buffer.clear();
		}
	}
}
