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

#include <math.h>
#include "g12buffer.h"
#include "loadimage.h"

#define MAX_GAIN  G12BUFFER_MAX_VALUE
#define MIN_GAIN  (1 / 1000.0)

#define MAX_OFFSET (G12BUFFER_MAX_VALUE)
#define MIN_OFFSET (-G12BUFFER_MAX_VALUE)

g12BufferDialog::g12BufferDialog(QWidget *parent)
    : QDialog(parent)
{
	ui.setupUi(this);
	inputBuffer = NULL;
	showBuffer = NULL;

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


	/* Histogram */
	connect(this, SIGNAL(notifyBufferChange(G12Buffer *)), &histogram, SLOT(notifyBufferChangeSlot(G12Buffer *)));

	notifyBufferChange(inputBuffer);

	connect(ui.histogramButton, SIGNAL(pressed()), &histogram, SLOT(show()));

	/* Now gain ad offset */
	// Offset
	gParams.offset = 0;
	QValidator *offsetValidator = new QIntValidator(MIN_OFFSET,MAX_OFFSET,this);
	ui.offsetEdit->setValidator(offsetValidator);
	ui.offsetEdit->setText(QString::number(gParams.offset));
	ui.offsetSlider->setMaximum(MAX_OFFSET);
	ui.offsetSlider->setMinimum(MIN_OFFSET);
	ui.offsetSlider->setValue(gParams.offset);
	connect(ui.offsetEdit, SIGNAL(textChanged(QString)), this, SLOT(updateOffsetSlider(QString)));
	connect(ui.offsetSlider, SIGNAL(valueChanged(int)), this, SLOT(updateOffsetText(int)));

	//Gain
	gParams.gain = 1;
	QValidator *gainValidator = new QDoubleValidator(MIN_GAIN,(double)MAX_GAIN,4,this);
	ui.gainEdit->setValidator(gainValidator);
	ui.gainEdit->setText(QString::number(gParams.gain));
	ui.gainSlider->setMaximum(100);
	ui.gainSlider->setMinimum(-100);
	ui.gainSlider->setValue(0);
	connect(ui.gainEdit, SIGNAL(textChanged(QString)), this, SLOT(updateGainSlider(QString)));
	connect(ui.gainSlider, SIGNAL(valueChanged(int)), this, SLOT(updateGainText(int)));

	suppressRecalculate = false;
}

void g12BufferDialog::updateOffsetSlider (QString string)
{
	bool ok;
	int value = string.toInt(&ok, 10);
	if (!ok)
		return;

	bool blocked = ui.offsetSlider->blockSignals(true);
	ui.offsetSlider->setValue(value);
	ui.offsetSlider->blockSignals(blocked);
	gParams.offset = value;
	emit parametersChanged(gParams);
	notifyRecalculate();

}

void g12BufferDialog::updateOffsetText (int val)
{
	bool blocked = ui.offsetEdit->blockSignals(true);
	ui.offsetEdit->setText(QString::number(val));
	ui.offsetEdit->blockSignals(blocked);

	gParams.offset = val;
	emit parametersChanged(gParams);
	notifyRecalculate();
}


void g12BufferDialog::updateGainSlider (QString string)
{
	bool ok;
	double value = string.toDouble(&ok);
	double loge = log(value);
	double log1_05 = log(1.05);
	value = loge / log1_05;

	if (!ok)
		return;

	bool blocked = ui.gainSlider->blockSignals(true);
	ui.gainSlider->setValue(value);
	ui.gainSlider->blockSignals(blocked);

	gParams.gain = value;
	emit parametersChanged(gParams);
	notifyRecalculate();
}

void g12BufferDialog::updateGainText (int val)
{
	double value = pow(1.05, val);
	bool blocked = ui.gainEdit->blockSignals(true);
	ui.gainEdit->setText(QString::number(value));
	ui.gainEdit->blockSignals(blocked);
	gParams.gain = value;
	emit parametersChanged(gParams);
	notifyRecalculate();
}

void g12BufferDialog::parametersChangedSlot(GainParameters gParamNew)
{
	gParams = gParamNew;
	bool blocked = ui.gainEdit->blockSignals(true);
	ui.gainEdit->setText(QString::number(gParams.gain));
	ui.gainEdit->blockSignals(blocked);

	double loge = log(gParams.gain);
	double log1_05 = log(1.05);
	double value = loge / log1_05;
	blocked = ui.gainSlider->blockSignals(true);
	ui.gainSlider->setValue(value);
	ui.gainSlider->blockSignals(blocked);

	blocked = ui.offsetSlider->blockSignals(true);
	ui.offsetSlider->setValue(gParams.offset);
	ui.offsetSlider->blockSignals(blocked);

	blocked = ui.offsetEdit->blockSignals(true);
	ui.offsetEdit->setText(QString::number(gParams.offset));
	ui.offsetEdit->blockSignals(blocked);

	notifyRecalculate();
}



G12Buffer *g12BufferDialog::getBuffer() const
{
	return inputBuffer;
}

void g12BufferDialog::notifyRecalculate(void)
{
	if (suppressRecalculate)
		return;
	if (inputBuffer == NULL)
		return;
	G12Buffer *oldShowBuffer;
	oldShowBuffer = showBuffer;
	showBuffer = g12BufferClone(inputBuffer);
	g12BufferGainOffset(showBuffer, gParams.gain, gParams.offset);
	emit notifyBufferChange(showBuffer);
	if (ui.widget->isVisible())
		ui.widget->update();

	if (oldShowBuffer != NULL)
		g12BufferDelete(oldShowBuffer);
}


void g12BufferDialog::notifyBufferChangeSlot(G12Buffer *buffer)
{
	inputBuffer = buffer;
	notifyRecalculate();
}

void g12BufferDialog::pointSelected(QPoint p)
{
	int x = p.x();
	int y = p.y();
	if (inputBuffer != NULL)
	{
		QString stats = QString("(%1,%2) %3").arg(x).arg(y).arg(G12ELEM(inputBuffer, x, y));
		ui.statisticsText->setText(stats);
	}
}

void g12BufferDialog::histogramShow()
{
	histogram.show();
}

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

void g12BufferDialog::mouseChild(QMouseEvent *event)
{
	if (showBuffer == NULL)
		return;
	int x = event->x();
	int y = event->y();
	if (x > 0 && x < showBuffer->w && y >0 && y < showBuffer->w)
	{
		pointSelected(event->pos());
	}
}

g12BufferDialog::~g12BufferDialog()
{

}
