#include "sgmdialog.h"
#include "sgm.h"

#include <qpainter.h>
#include "g12Image.h"

SGMDialog::SGMDialog(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.leftBufferButton,     SIGNAL(released()), this, SLOT(update()));
	connect(ui.rightBufferButton,    SIGNAL(released()), this, SLOT(update()));
	connect(ui.leftDisparityButton,  SIGNAL(released()), this, SLOT(update()));
	connect(ui.rightDisparityButton, SIGNAL(released()), this, SLOT(update()));
	connect(ui.totalDisparityButton, SIGNAL(released()), this, SLOT(update()));

	buffer1 = NULL;
	buffer2 = NULL;

    dispLeft = NULL;
    dispRight = NULL;
    totalDisp = NULL;
    trueDisp = NULL;

    pathes[PATH_TOP_LEFT_BIT]  = ui.pathBox0;
    pathes[PATH_TOP_BIT]       = ui.pathBox1;
    pathes[PATH_TOP_RIGHT_BIT] = ui.pathBox2;
    pathes[PATH_LEFT_BIT]      = ui.pathBox3;

    pathes[PATH_RIGHT_BIT]        = ui.pathBox5;
    pathes[PATH_BOTTOM_LEFT_BIT]  = ui.pathBox6;
    pathes[PATH_BOTTOM_BIT]       = ui.pathBox7;
    pathes[PATH_BOTTOM_RIGHT_BIT] = ui.pathBox8;

	for (int i = 0; i < 8; i++)
	{
		pathes[i]->setChecked(true);
	}

    ui.maxDisparityBox->setMinimum(1);
    ui.maxDisparityBox->setMaximum(700);
    ui.maxDisparityBox->setValue(30);



    ui.closePenaltyBox->setMinimum(0);
    ui.closePenaltyBox->setMaximum(0xFFF);
    ui.closePenaltyBox->setValue( 5 << 4);

    ui.farPenaltyBox->setMaximum(0xFFF);
    ui.farPenaltyBox->setMinimum(0);
    ui.farPenaltyBox->setValue(40 << 4);

    ui.progressBar->setValue(0);

	connect(ui.recalculateButton, SIGNAL(released()), this, SLOT(recalculate()));

	instance = this;

}

void SGMDialog::maxDisparityChangedSlot(int maxDisparity)
{
	ui.maxDisparityBox->setValue(maxDisparity);
}

void SGMDialog::buffersChangedSlot(G12Buffer *buffer1, G12Buffer *buffer2)
{
	this->buffer1 = buffer1;
	this->buffer2 = buffer2;
	this->update();
	//ui.maxDisparityBox->setValue(maxDisparity);
}

SGMDialog *SGMDialog::instance = NULL;

void SGMDialog::callback(int path, int persent)
{
	if (instance != NULL)
	{
		instance->ui.progressBar->setValue(100 * path / (PATH_LIMIT - 1));
	}
}

void SGMDialog::recalculate(void)
{
	if (buffer1 == NULL || buffer2 == NULL)
		return;

	unsigned long time = clock();
	int maxDisparity = ui.maxDisparityBox->value();
	int closePenalty = ui.closePenaltyBox->value();
	int farPenalty   = ui.farPenaltyBox->value();

	if (dispLeft != NULL)
		g12BufferDelete(dispLeft);
	if (dispRight != NULL)
		g12BufferDelete(dispRight);

	G12Buffer *old = totalDisp;
	DisparityBuffer *oldDisparity = trueDisp;

	int mask = 0;
	for (int i = 0; i < 8; i++)
	{
		if (pathes[i]->isChecked())
			mask |= (1 << i);
	}

	ui.progressBar->setValue(0);
	dispLeft = sgm_PC16(buffer2, buffer1, -maxDisparity , closePenalty, farPenalty, NULL, NULL, NULL, mask, SGMDialog::callback);
	ui.progressBar->setValue(100);

	time = clock() - time;
	printf("PC16 implementation runs for %lf s\n", ((double)time) / CLOCKS_PER_SEC);
	time = clock();
	ui.progressBar->setValue(0);
	dispRight = sgm_PC16(buffer2, buffer1, maxDisparity , closePenalty, farPenalty, NULL, NULL, NULL, mask, SGMDialog::callback);
	ui.progressBar->setValue(100);

	time = clock() - time;
	printf("PC16 implementation runs for %lf s\n", ((double)time) / CLOCKS_PER_SEC);
	//recount = 0;
	int i,j;


	totalDisp = g12BufferCreate(dispRight->h, dispRight->w);
	trueDisp = disparityBufferCreate(dispRight->h, dispRight->w);

	for (i = 0; i <  dispLeft->h; i++)
	{
		for (j = 0; j <  dispLeft->w; j++)
		{
			int leftDisparity = G12ELEM(dispLeft,j ,i) / (16.0 * 255.0) * maxDisparity;
			if (j - leftDisparity < 0)
			{
				continue;
			}
			int rightDisparity = G12ELEM(dispRight,j + leftDisparity ,i) / (16.0 * 255.0) * maxDisparity;
			if (leftDisparity - rightDisparity < 8 && leftDisparity - rightDisparity > -8)
			{
				G12ELEM(totalDisp, j, i) = G12ELEM(dispLeft,j,i);
				G12ELEM(trueDisp, j, i) = G12ELEM(dispLeft,j,i);
			}
		}
	}

	trueDisp->maxValue = 16 * 255;

	emit setBuffers(buffer1, trueDisp, 255.0);

	if (old != NULL)
		g12BufferDelete(old);
	if (oldDisparity != NULL)
		disparityBufferDelete(oldDisparity);


	this->update();
}

SGMDialog::~SGMDialog()
{
	if (dispLeft != NULL)
		g12BufferDelete(dispLeft);
	if (dispRight != NULL)
		g12BufferDelete(dispRight);
	if (totalDisp != NULL)
		g12BufferDelete(totalDisp);
}

void SGMDialog::repaintChild(QPaintEvent *event, QWidget *who)
{

	QPainter painter(who);

	if (ui.leftBufferButton->isChecked() && buffer1 != NULL)
	{
		g12Image image(buffer1);
		painter.drawImage(QPoint(0,0), image);
		return;
	}
	if (ui.rightBufferButton->isChecked() && buffer2 != NULL)
	{
		g12Image image(buffer2);
		painter.drawImage(QPoint(0,0), image);
		return;
	}


	if (ui.leftDisparityButton->isChecked() && dispLeft != NULL)
	{
		g12Image image(dispLeft);
		painter.drawImage(QPoint(0,0), image);
		return;
	}
	if (ui.rightDisparityButton->isChecked() && dispRight != NULL)
	{
		g12Image image(dispRight);
		painter.drawImage(QPoint(0,0), image);
		return;
	}

	if (ui.totalDisparityButton->isChecked() && totalDisp != NULL)
	{
		g12Image image(totalDisp);
		painter.drawImage(QPoint(0,0), image);
		return;
	}

}

void SGMDialog::mouseChild(QMouseEvent *event)
{

}
