// -*- mode: c++; c-basic-offset: 4; -*-

#include "MyApplication.h"
#include "MyWidget.h"

void MyWidget::refreshScreen() {
	onyx::screen::ScreenProxy::instance().updateWidget(this, onyx::screen::ScreenProxy::GU, false, onyx::screen::ScreenCommand::WAIT_NONE);
}

void MyWidget::paintEvent(QPaintEvent *e) {
	QPainter painter(this);

	// draw actual image
	painter.resetTransform();
	painter.translate(800.0,0);
	painter.rotate(90.0);	
	painter.drawPixmap(QPoint(0,0),*pixmap);

	if(debugEnabled)
	{
		// debug info
		painter.resetTransform();
		QFont font("", 20, QFont::Normal);
		painter.setFont(font);
		painter.setPen(Qt::white);
		painter.drawText(rect(), Qt::AlignCenter, debugMessage->toAscii());
	}
}

void MyWidget::imageDataReady() 
{
	QByteArray data = port->readAll();

	debugMessage->truncate(0);	
	debugMessage->append(QString("entered pngReady()\n"));
	debugMessage->append(QString("data: " + QString::number(data.length()) + " bytes\n"));

	QByteArray *startOfNewImageArray = new QByteArray();
	if(data.indexOf('*') > -1)  // start marker
	{
		QList<QByteArray> splittedArraysByAsterisk = data.split('*');
		if(imageStartFlag == false) {
			imageStartFlag = true;	
			pixmapByteArray->append(splittedArraysByAsterisk[1]);
			debugMessage->append(QString("image start\n"));
		} else { // imageStartFlag == true
			// means we've encountered end of image
			// and new one has already begun
			imageEndFlag = true;
			debugMessage->append(QString("image end (with new one following)\n"));
			// probably # is around as well in the first half
			QList<QByteArray> splittedArraysByHash = splittedArraysByAsterisk[0].split('#');
			debugMessage->append(QString("image end is " + QString::number(splittedArraysByHash[0].size()) +  " bytes\n"));
			pixmapByteArray->append(splittedArraysByHash[0]);
			if(splittedArraysByAsterisk[1].size() > 0) 
			{
				startOfNewImageArray->append(splittedArraysByAsterisk[1]);
				debugMessage->append(QString("simultaneous start of new image, new chunk " + QString::number(startOfNewImageArray->size())  +  " bytes\n"));
			}
		}
	} 
	else if(data.indexOf('#') > -1) 
		// has to be end of file, because
		// we already handled all other cases
		// above
	{
		imageEndFlag = true;	
		QList<QByteArray> splittedArraysByHash = data.split('#');
		pixmapByteArray->append(splittedArraysByHash[0]);
		debugMessage->append(QString("image end\n"));

		// this shouldn't really happent but does
		// we'll miss this frame but next ones will be ok
		if(imageEndFlag && !imageStartFlag)
		{
			imageStartFlag = true;
		}
	} else {
		// plain image data
		debugMessage->append(QString("just image data chunk\n"));
		pixmapByteArray->append(data);
	}
	debugMessage->append(QString("we have " + QString::number(pixmapByteArray->length()) + " total bytes\n"));

	if(imageStartFlag && imageEndFlag)
	{
		// Base 64 decode
		debugMessage->append(QString("image start and end received\n"));
		debugMessage->append(QString("decoding base 64\n"));
		QByteArray decodedData = QByteArray::fromBase64(*pixmapByteArray); 
		debugMessage->append(QString("base 64 length " + QString::number(decodedData.length()) +  " \n"));

		// decode image
		QPixmap *pixmap_temp = new QPixmap(); 
		debugMessage->append(QString("decoding image\n"));

		bool isValidPng = pixmap_temp->loadFromData(decodedData);

		if(isValidPng) {
			debugMessage->append(QString("valid image\n"));
			// delete old image
			delete pixmap;
			// allocate new image	
			pixmap = new QPixmap();
			pixmap->loadFromData(decodedData);
			//invalidImageFlag = false;
		} else {
			debugMessage->append(QString("invalid image\n"));
			//invalidImageFlag = true;
		}
		delete pixmap_temp;

		// make room for new data, clear state
		debugMessage->append(QString("make room for new data\n"));
		pixmapByteArray->truncate(0);	
		imageStartFlag = false;
		imageEndFlag = false;

		if(startOfNewImageArray->size() > 0)
		{
			debugMessage->append(QString("new image started, setting flag to true\n"));
			imageStartFlag = true;	
			debugMessage->append(QString("initializing new image with " + QString::number(startOfNewImageArray->size()) +  " bytes\n"));
			pixmapByteArray->append(*startOfNewImageArray);
		}
		delete startOfNewImageArray;

		debugMessage->append(QString("refresh screen\n"));

		repaint();
	}
}


bool MyWidget::event(QEvent * event)
{
	bool ret = QWidget::event(event);
	if (event->type() == QEvent::UpdateRequest)
	{
		refreshScreen();
	}
	return ret;
}

void MyWidget::keyReleaseEvent(QKeyEvent *ke)
{
	ke->accept();
	if (ke->key() == Qt::Key_Escape)
	{
		port->close();
		qApp->exit();
	}
	if (ke->key() == Qt::Key_PageDown)
	{
		onyx::screen::ScreenProxy::instance().updateWidget(this, onyx::screen::ScreenProxy::GC, false, onyx::screen::ScreenCommand::WAIT_NONE);
	}
	if (ke->key() == Qt::Key_PageUp)
	{
		// for showing debug data when no new frames are coming in
		update();
	}
	if (ke->key() == Qt::Key_Down)
	{
		// just flip debugEnabled value
		debugEnabled = !debugEnabled;
	}
}

