#include "signaturesdialog.h"
#include "g12Image.h"
#include <qpainter.h>
#include <qevent.h>
#include "signaturewidget.h"
#include <qmessagebox.h>

#define SET_BOX_ARRAY(X) sigBoxes[X] = ui.isSig##X

SignaturesDialog::SignaturesDialog(QWidget *parent)
    : QDialog(parent)
{
	ui.setupUi(this);

	/* Main UI*/
	connect(ui.widget, SIGNAL(askParentRepaint(QPaintEvent *, QWidget *)), this, SLOT(repaintChild(QPaintEvent *, QWidget *)));
	connect(ui.widget, SIGNAL(notifyParentMouseMove(QMouseEvent* )), this, SLOT(mouseChild(QMouseEvent *)));

	connect(ui.distributionButton, SIGNAL(pressed()), &sdw, SLOT(show()));
	connect(ui.distributionButton, SIGNAL(pressed()), &sdw, SLOT(regenerateTables()));
	connect(this, SIGNAL(notifyCoratgesChange(CortageList *, G12Buffer *)), &sdw, SLOT(signatureListChanged(CortageList *)));

	connect(&sdw, SIGNAL(updatePoints(signature_t)), this, SLOT(regeneratePoints(signature_t)));

//	sdw.signatureListChanged(NULL);
	/*Recalculate Button*/
	connect(ui.recalculateButton, SIGNAL(pressed()), this, SLOT(notifyRecalculate()));


	SET_BOX_ARRAY(0);  SET_BOX_ARRAY(1);   SET_BOX_ARRAY(2);  SET_BOX_ARRAY(3);
	SET_BOX_ARRAY(4);  SET_BOX_ARRAY(5);   SET_BOX_ARRAY(6);  SET_BOX_ARRAY(7);
	SET_BOX_ARRAY(8);  SET_BOX_ARRAY(9);   SET_BOX_ARRAY(10); SET_BOX_ARRAY(11);
	SET_BOX_ARRAY(12); SET_BOX_ARRAY(13);  SET_BOX_ARRAY(14); SET_BOX_ARRAY(15);

	int i;
	sParam.mask = 0;
	for (i = 1; i < 16; i++)
	{
		sigBoxes[i]->setChecked(true);
		sParam.mask |= (1 << i);
		connect(sigBoxes[i], SIGNAL(stateChanged(int)), this, SLOT(maskChanged()));
	}



	input = NULL;
	integralInput = NULL;
	signatures = NULL;
	cortageList = NULL;
	ui.statisticsLabel->setText("No signatures");


	sParam.epsilonHighLimit = 8;
	sParam.epsilonLowLimit = 1;
	sParam.sdevHighLimit = 100;
	sParam.sdevLowLimit = 1;

	ui.epsHighBox->setMaximum(1000);
	ui.epsHighBox->setMinimum(0);
	ui.epsHighBox->setValue(sParam.epsilonHighLimit);

	ui.epsLowBox->setMaximum(1000);
	ui.epsLowBox->setMinimum(0);
	ui.epsLowBox->setValue(sParam.epsilonLowLimit);

	ui.sDevLowBox->setMaximum(1000);
	ui.sDevLowBox->setMinimum(0);
	ui.sDevLowBox->setValue(sParam.sdevLowLimit);

	ui.sDevHighBox->setMaximum(1000);
	ui.sDevHighBox->setMinimum(0);
	ui.sDevHighBox->setValue(sParam.sdevHighLimit);

	connect(ui.epsHighBox, SIGNAL(valueChanged(int)), this, SLOT(epsHighChanged(int)));
	connect(ui.epsLowBox, SIGNAL(valueChanged(int)), this, SLOT(epsLowChanged(int)));
	connect(ui.sDevHighBox, SIGNAL(valueChanged(int)), this, SLOT(sDevHighChanged(int)));
	connect(ui.sDevLowBox, SIGNAL(valueChanged(int)), this, SLOT(sDevLowChanged(int)));


	/* The remember list*/
	//ui.widgetInfo->setMinimumHeight(153);
	//ui.widgetInfo->setLayout(new QLayout())

	infoLayout = NULL;


	pointsToShow.clear();
}

void SignaturesDialog::maskChanged(void)
{
	sParam.mask = 0;
	int i;
	for (i = 1; i < 16; i++)
	{
		sParam.mask |= ((sigBoxes[i]->isChecked()) ? (1 << i) : 0);
	}
	ui.recalculateButton->setEnabled(true);
	emit parametersChanged(sParam);
}

void SignaturesDialog::sDevHighChanged(int value)
{
	sParam.sdevHighLimit = value;
	ui.recalculateButton->setEnabled(true);
	emit parametersChanged(sParam);
}

void SignaturesDialog::sDevLowChanged(int value)
{
	sParam.sdevLowLimit = value;
	ui.recalculateButton->setEnabled(true);
	emit parametersChanged(sParam);
}

void SignaturesDialog::epsHighChanged(int value)
{
	sParam.epsilonHighLimit = value;
	ui.recalculateButton->setEnabled(true);
	emit parametersChanged(sParam);
}

void SignaturesDialog::epsLowChanged(int value)
{
	sParam.epsilonLowLimit = value;
	ui.recalculateButton->setEnabled(true);
	emit parametersChanged(sParam);
}

void SignaturesDialog::parametersChangedSlot(SignatureParameters sParamNew)
{
	sParam = sParamNew;
	bool block;
	block = ui.epsHighBox->blockSignals(true);
	ui.epsHighBox->setValue(sParam.epsilonHighLimit);
	ui.epsHighBox->blockSignals(block);

	block = ui.epsLowBox->blockSignals(true);
	ui.epsLowBox->setValue(sParam.epsilonLowLimit);
	ui.epsLowBox->blockSignals(block);

	block = ui.sDevHighBox->blockSignals(true);
	ui.sDevHighBox->setValue(sParam.sdevHighLimit);
	ui.sDevHighBox->blockSignals(block);

	block = ui.sDevLowBox->blockSignals(true);
	ui.sDevLowBox->setValue(sParam.sdevLowLimit);
	ui.sDevLowBox->blockSignals(block);

	int i;
	for (i = 1; i < 16; i++)
	{
		block = sigBoxes[i]->blockSignals(true);
		sigBoxes[i]->setChecked(sParam.mask & (1 << i));
		sigBoxes[i]->blockSignals(block);
	}

	ui.recalculateButton->setEnabled(true);
}

void SignaturesDialog::notifyBufferChangeSlot(G12Buffer *buf)
{
	input = buf;
	if (input == NULL)
		return;
	ui.recalculateButton->setEnabled(true);
	this->update();
}

void SignaturesDialog::notifyRecalculate( void )
{
	if (input == NULL)
		return;
	if (integralInput != NULL)
		integralBufferDelete(integralInput);

	if (signatures != NULL)
		signaturesBufferDelete(signatures);

	if (cortageList != NULL)
		cortageListDelete(cortageList);



	integralInput = integralBufferCreateFromG12(input);
	signatures = signaturesBufferCreateFromIntegral3piece(integralInput, &sParam);
	cortageList = cortageListGenerate(signatures);
	cortageListResort(cortageList);
	ui.widget->update();
	ui.recalculateButton->setEnabled(false);
	QString infoSting = QString("%1 different signatures").arg(coratgeListDifferentSignatures(cortageList));
	ui.statisticsLabel->setText(infoSting);
	emit notifyCoratgesChange(cortageList, input);
}

void SignaturesDialog::regeneratePoints(signature_t sig)
{
	int count = 0;
	int num = cortageListSortedGetSignature(cortageList, sig);
	deleteChildWidgets();
	pointsToShow.clear();

	if (cortageList->cortages[num].signature != sig)
	{
		QMessageBox::information(this, "Problem ", QString("Could not"),  "OK");
		num = cortageListSortedGetSignature(cortageList, sig);
	}
	while (cortageList->cortages[num].signature == sig && num < cortageList->active)
	{
		int px = cortageList->cortages[num].point.x;
		int py = cortageList->cortages[num].point.y;
		pointsToShow.append(QPoint(px, py));

		if (count < 10)
		{
			addChildWidget(px, py);
		}

		num ++;
		count++;
	}

	//TODO: Remove memory leak
	infoLayout->addItem(new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum));
	ui.statisticsLabel->setText(QString("Selected: %1").arg(count));

	ui.widget->update();
}

void SignaturesDialog::repaintChild(QPaintEvent *event, QWidget *who)
{
	QPainter painter(who);
	if (input == NULL)
	{
		painter.drawText(0,0, who->width(), who->height(), Qt::AlignHCenter | Qt::AlignVCenter, QString("NO IMAGE LOADED"));
		return;
	}
	g12Image image(input);
	painter.drawImage(QPoint(0,0), image);

	painter.setPen(Qt::red);
	if (cortageList != NULL)
	{
		int num = cortageListSortedGetSignature(cortageList, sigToDraw);
		while (cortageList->cortages[num].signature == sigToDraw && num < cortageList->active)
		{
			int x = cortageList->cortages[num].point.x;
			int y = cortageList->cortages[num].point.y;
			painter.drawRect(x - 1, y - 1, 2, 2);
			num ++;
		}
	}

	painter.setPen(Qt::blue);
	for (int j = 0; j < pointsToShow.size(); j++)
	{
		QPoint p =  pointsToShow[j];
		painter.drawRect(p.x() - 1, p.y() - 1, 2, 2);
	}
}

void SignaturesDialog::deleteChildWidgets( void )
{
	for (int i = 0; i < infos.size(); i++)
		delete infos.at(i);
	infos.clear();
	if (infoLayout != NULL)
		delete infoLayout;

	infoLayout = new QHBoxLayout();
	infoLayout->setSpacing(6);
	infoLayout->setObjectName(QString::fromUtf8("hboxLayout1"));
	ui.vboxLayout->addLayout(infoLayout);

}

void SignaturesDialog::addChildWidget(int x, int y)
{
	if (integralInput == NULL)
		return;
	SignatureWidget* signatureWidget = new SignatureWidget(this);
	signatureWidget->updateSignature(integralInput, x, y, sParam);
	infoLayout->addWidget(signatureWidget);
	signatureWidget->show();
	infos.append(signatureWidget);

}

void SignaturesDialog::mouseChild(QMouseEvent *event)
{
	if (event->type() == QEvent::MouseMove)
	{
		int x = event->x();
		int y = event->y();
		if (signatures != NULL && x >=0 && x < signatures->w && y >= 0 && y < signatures->h)
		{
			sigToDraw = SELEM(signatures, x, y);
		}
		ui.widget->update();
		return;
	}
	if (event->type() == QEvent::MouseButtonPress)
	{
		int x = event->x();
		int y = event->y();
		if (signatures == NULL || x < 0 || x > signatures->w || y < 0 || y > signatures->h)
			return;

		signature_t sig = SELEM(signatures, x, y);
		regeneratePoints(sig);
		return;
	}
}


SignaturesDialog::~SignaturesDialog()
{

}
