/*
 * CGen2TagPowerReadMeasurement.cpp
 *
 *  Created on: 05.05.2011
 *      Author: stefan.detter
 */

#include "CGen2TagPowerReadMeasurement.h"

#include <ui_CGen2TagEngineeringDialog.h>
#include <QrfeReaderInterfaceGlobal>
#include <QrfeReaderInterface>
#include <reader/QrfeRfePurReader>
#include <tag/QrfeGen2Tag>
#include <epc/EPC_Defines>

#include <QrfeResourceGlobal>

#include <Cache.h>
#include <def.h>

#include <QPen>
#include <QMessageBox>
#include <QStandardItemModel>
#include <QDir>
#include <QFileInfo>

#include <QrfeSleeper>
#include <QrfeQwt>
#include <QrfeGuiLibGlobal>

#include <qwt_plot.h>
#include <qwt_color_map.h>
#include <qwt_legend.h>
#include <qwt_plot_spectrogram.h>

#include <qwt_scale_widget.h>
#include <qwt_plot_layout.h>
#include <qwt_plot_magnifier.h>
#include <qwt_plot_panner.h>
#include <qwt_plot_canvas.h>


CGen2TagPowerReadMeasurement::CGen2TagPowerReadMeasurement(QTextEdit* infoEdit, QWidget* parent)
	: TagTabWidget(tr("Power vs. Read Count Measurement"), parent)
	, m_parent(parent)
{
	ui.setupUi(this);
	setInfoEdit(infoEdit);

	connect(ui.startFreqSweepButton,	SIGNAL(clicked()),
			this, 							  	  SLOT(startButtonClicked()));
	connect(ui.exportSweepButton, 		SIGNAL(clicked()),
			this, 							  	  SLOT(exportSweepResults()));

	connect(ui.startFrequencyBox, 	SIGNAL(valueChanged(double)),
			this, 							  SLOT(sweepValuesChanged()));
	connect(ui.stopFrequencyBox,		SIGNAL(valueChanged(double)),
			this, 							  SLOT(sweepValuesChanged()));
	connect(ui.stepsFrequencyBox, 	SIGNAL(valueChanged(double)),
			this, 							  SLOT(sweepValuesChanged()));

	connect(ui.startAttenuationBox,SIGNAL(valueChanged(int)),
		this, 							  SLOT(sweepValuesChanged()));
	connect(ui.stopAttenuationBox, SIGNAL(valueChanged(int)),
		this, 							  SLOT(sweepValuesChanged()));
	connect(ui.stepsAttenuationBox,SIGNAL(valueChanged(int)),
		this, 							  SLOT(sweepValuesChanged()));


	m_freqSweepValueModel = new QStandardItemModel(this);
	m_freqSweepValueModel->setColumnCount(3);
	ui.freqSweepTableView->setModel(m_freqSweepValueModel);

	m_data = new QwtMatrixRasterData();
	m_data->setResampleMode(QwtMatrixRasterData::BilinearInterpolation);

	m_freqSweepPlot = new QwtPlot(m_parent);
	ui.freqSweepPlotLayout->addWidget(m_freqSweepPlot);

	m_spectrogram = new QwtPlotSpectrogram();
	m_spectrogram->setRenderThreadCount(0);
	m_spectrogram->setColorMap( colorMap() );
	m_spectrogram->attach(m_freqSweepPlot);

    // A color bar on the right axis
    QwtScaleWidget *rightAxis = m_freqSweepPlot->axisWidget(QwtPlot::yRight);
    rightAxis->setColorBarEnabled(true);
    rightAxis->setColorBarWidth(10);
    rightAxis->setColorMap(QwtInterval(0.0, 1.0), colorMap() );

	m_freqSweepPlot->plotLayout()->setAlignCanvasToScales(true);
	m_freqSweepPlot->setAxisMaxMinor(QwtPlot::xBottom, 0);
	m_freqSweepPlot->setAxisTitle(QwtPlot::xBottom, "Attenuation (steps)");
	m_freqSweepPlot->setAxisMaxMinor(QwtPlot::yLeft, 0);
	m_freqSweepPlot->setAxisTitle(QwtPlot::yLeft, "Frequency (MHz)");
	m_freqSweepPlot->enableAxis(QwtPlot::yRight);
	m_freqSweepPlot->setAxisTitle(QwtPlot::yRight, "Read Count");

	m_measurementActive = false;
	m_continueMeasurement = true;

	m_reader 	= 0;
	m_tag 		= 0;

	License::d->remainingExecutionCount(this, EXEC_COUNT_ENGINEERING_TAG_POWER_VS_READ_COUNT);
}

CGen2TagPowerReadMeasurement::~CGen2TagPowerReadMeasurement()
{
}


bool CGen2TagPowerReadMeasurement::init(QrfeReaderInterface* reader, QrfeTagInterface* tag)
{
	m_reader 	= reader;

	if(qobject_cast<QrfeGen2Tag*>(tag) == 0)
		return false;
	else
		m_tag = qobject_cast<QrfeGen2Tag*>(tag);

	connect(m_reader, 		SIGNAL(exclusive_cyclicInventory(const QrfeGlobal::TagReadEvent& )),
			this, 			  SLOT(cyclicInventory(const QrfeGlobal::TagReadEvent& )), Qt::DirectConnection );

	ui.progressBar->setValue(0);
	ui.progressBar->setEnabled(false);

	ushort maxAtt;
	m_reader->getMaxAttenuation(maxAtt);
	ui.startAttenuationBox->setValue(maxAtt/2);
	ui.startAttenuationBox->setMaximum(maxAtt);
	ui.stopAttenuationBox->setValue(maxAtt);
	ui.stopAttenuationBox->setMaximum(maxAtt);
	ui.stepsAttenuationBox->setMaximum(maxAtt);

	m_maxReadCount = 1;

	clearValues();
	sweepValuesChanged();

	ui.exportSweepButton->setEnabled(false);

	m_measurementActive = false;

	reloadLicenseData();

	return true;
}

void CGen2TagPowerReadMeasurement::deinit()
{
	disconnect(	m_reader, 		SIGNAL(exclusive_cyclicInventory(const QrfeGlobal::TagReadEvent& )),
				this, 			  SLOT(cyclicInventory(const QrfeGlobal::TagReadEvent& )) );

	m_reader 	= 0;
	m_tag 		= 0;
}

bool CGen2TagPowerReadMeasurement::hasExecutionCount()
{
//	if(!License::d->hasLicense(QrfeLicense::ReaderSuite_EngineeringLicense))
//		return true;
	return false;
}


void CGen2TagPowerReadMeasurement::startButtonClicked()
{
	if(m_measurementActive)
		m_continueMeasurement = false;
	else{
		m_continueMeasurement = true;
		QTimer::singleShot(0, this, SLOT(runFrequencySweep()));
	}
}

void CGen2TagPowerReadMeasurement::runFrequencySweep()
{
	if(m_reader == 0 || m_tag == 0 || m_measurementActive)
		return;

	m_measurementActive = true;

	//-------------------------------------------------------------------------------------------
	// Get and Check Input Values

	ulong startFreq = ui.startFrequencyBox->value() * 1000;
	ulong stopFreq = ui.stopFrequencyBox->value() * 1000;
	ulong stepsFreq = ui.stepsFrequencyBox->value() * 1000;

	ushort startAtt = ui.startAttenuationBox->value();
	ushort stopAtt = ui.stopAttenuationBox->value();
	ushort stepsAtt = ui.stepsAttenuationBox->value();

	int timeout = ui.timeoutAttenuationBox->value();

	uint freqSteps = ((stopFreq - startFreq) / stepsFreq) + 1;
	uint attSteps = ((stopAtt - startAtt) / stepsAtt) + 1;
	uint generalSteps = freqSteps * attSteps;

	clearValues();

	if(stopFreq < startFreq)
	{
		QMessageBox::critical(m_parent, "Error", "The start frequency value for the sweep must be lower than the stop frequency value!");
		m_measurementActive = false;
		return;
	}

	if(stopAtt < startAtt)
	{
		QMessageBox::critical(m_parent, "Error", "The start attenuation value for the sweep must be lower than the stop attenuation value!");
		m_measurementActive = false;
		return;
	}

	//-------------------------------------------------------------------------------------------
	// Prepare GUI / Disable all parts
	License::d->decrementExecutionCount(this);
	setWorking();
	clearInfo();

	ui.exportSweepButton->setEnabled(false);
	ui.frequencyBox->setEnabled(false);
	ui.minimumPowerBox->setEnabled(false);
	ui.scanBox->setEnabled(false);

	ui.startFreqSweepButton->setText("Stop");
	ui.startFreqSweepButton->setIcon(QIcon(QrfeGlobal::getButtonIconResourcePath("stop")));

	ui.progressBar->setEnabled(true);
	ui.progressBar->setValue(0);
	ui.progressBar->setMaximum(generalSteps);


	//-------------------------------------------------------------------------------------------
	// Measurement

	m_freqSweepValueModel->setColumnCount( ((startAtt - stopAtt) / stepsAtt) + 1 );
	QStringList labels;
	labels << "Frequency (MHz)";
	for(ushort att = startAtt; att <= stopAtt; att += stepsAtt)
	{
		labels << QString::number(att) + " steps\nAttenuation";
	}
	m_freqSweepValueModel->setHorizontalHeaderLabels(labels);


	QList<double> data;
	QList<double> column;
	m_maxReadCount = 1;

	infoAppend("-- Starting measurement  --");
	for(ulong freq = startFreq; freq <= stopFreq; freq += stepsFreq)
	{
		if(!m_continueMeasurement)
			break;

		QList<QStandardItem*> items;
		items << new QStandardItem(QString("%1").arg(((double)freq)/1000.0));

		column.clear();
		for(ushort att = startAtt; att <= stopAtt; att += stepsAtt)
		{
			ushort maxReadCount;
			measurePowerVsReadCount(freq, att, timeout, maxReadCount);

			items << new QStandardItem(QString("%1").arg(maxReadCount));


			column.append(maxReadCount);

			if(maxReadCount > m_maxReadCount){
				m_maxReadCount = maxReadCount;
			}

			ui.progressBar->setValue(ui.progressBar->value()+1);
			qApp->processEvents();
		}

		m_freqSweepValueModel->appendRow(items);

		data.append(column);
	}
	infoSetOK("-- Measurement ended--");

	//-------------------------------------------------------------------------------------------
	// Results to GUI
	if(m_continueMeasurement)
	{
		m_data->setInterval( Qt::XAxis, QwtInterval( startAtt, stopAtt, QwtInterval::IncludeBorders ) );
		m_data->setInterval( Qt::YAxis, QwtInterval( startFreq, stopFreq, QwtInterval::IncludeBorders ) );
		m_data->setInterval( Qt::ZAxis, QwtInterval( 0, m_maxReadCount ) );
		m_data->setValueMatrix(data.toVector(), column.size());

		m_spectrogram->setColorMap(colorMap());
		m_spectrogram->setData(m_data);

		m_freqSweepPlot->axisWidget(QwtPlot::yRight)->setColorMap(QwtInterval(0.0, m_maxReadCount), colorMap() );
		m_freqSweepPlot->setAxisScale(QwtPlot::yRight, 0, m_maxReadCount);
		m_freqSweepPlot->replot();
	}

	//-------------------------------------------------------------------------------------------
	// Restore GUI

	ui.progressBar->setValue(0);
	ui.progressBar->setEnabled(false);

	ui.startFreqSweepButton->setText("Start");
	ui.startFreqSweepButton->setIcon(QIcon(QrfeGlobal::getButtonIconResourcePath("start")));

	ui.exportSweepButton->setEnabled(true);
	ui.frequencyBox->setEnabled(true);
	ui.minimumPowerBox->setEnabled(true);
	ui.scanBox->setEnabled(true);

	m_measurementActive = false;

	setIdle();
	reloadLicenseData();
}

void CGen2TagPowerReadMeasurement::clearValues()
{
	if(m_reader == 0 || m_tag == 0)
		return;

	m_freqSweepPlot->setAxisScale(QwtPlot::yLeft, ui.startFrequencyBox->value() * 1000, ui.stopFrequencyBox->value() * 1000);
	m_freqSweepPlot->setAxisScale(QwtPlot::xBottom, ui.startAttenuationBox->value(), ui.stopAttenuationBox->value());
	m_freqSweepPlot->setAxisScale(QwtPlot::yRight, 0, m_maxReadCount);
	m_freqSweepPlot->replot();

	m_freqSweepValueModel->clear();
	m_freqSweepValueModel->setColumnCount(1);
	m_freqSweepValueModel->setHorizontalHeaderLabels(QStringList() << tr("Frequency (MHz)"));

	ui.freqSweepTableView->verticalHeader()->setVisible(false);
	ui.freqSweepTableView->horizontalHeader()->setStretchLastSection(false);
	ui.freqSweepTableView->resizeColumnsToContents();
}

void CGen2TagPowerReadMeasurement::sweepValuesChanged ( )
{
	if(m_reader == 0 || m_tag == 0)
		return;

	m_freqSweepPlot->setAxisScale(QwtPlot::yLeft, ui.startFrequencyBox->value() * 1000, ui.stopFrequencyBox->value() * 1000);
	m_freqSweepPlot->setAxisScale(QwtPlot::xBottom, ui.startAttenuationBox->value(), ui.stopAttenuationBox->value());
	m_freqSweepPlot->setAxisMaxMinor(QwtPlot::yLeft, 0);
	m_freqSweepPlot->setAxisScale(QwtPlot::yRight, 0, m_maxReadCount);
	m_freqSweepPlot->enableAxis(QwtPlot::yRight);
	m_freqSweepPlot->axisWidget(QwtPlot::yRight)->setColorMap(QwtInterval(0.0, m_maxReadCount), colorMap() );

	m_freqSweepPlot->replot();

	m_freqSweepValueModel->clear();
	m_freqSweepValueModel->setColumnCount(1);
	m_freqSweepValueModel->setHorizontalHeaderLabels(QStringList() << tr("Frequency (MHz)"));

	ui.freqSweepTableView->verticalHeader()->setVisible(false);
	ui.freqSweepTableView->horizontalHeader()->setStretchLastSection(false);
	ui.freqSweepTableView->resizeColumnsToContents();

}


void CGen2TagPowerReadMeasurement::measurePowerVsReadCount(ulong freq, ushort att, int timeout, ushort& maxReadCount)
{
	if(m_reader == 0 || m_tag == 0)
		return;

	infoSet("Measuring minimum power");

	if(m_reader->setFrequency(0, QList<uint>() << freq) != QrfeGlobal::RES_OK)
	{
		infoAppend("Could not set frequency to " + QString::number(freq) + "kHz");
		showNOK();
		maxReadCount = 0;
		return;
	}
	else
	{
		infoAppend("-- Frequency set to " + QString::number(freq) + "kHz --");
		showOK();
	}

	if(m_reader->setAttenuation(att) != QrfeGlobal::RES_OK)
	{
		infoAppend("Could not set attenuation to " + QString::number(att) + "steps --");
		showNOK();
		maxReadCount = 0;
		return;
	}
	else
	{
		infoAppend("-- Attenuation set to " + QString::number(att) + "steps --");
		showOK();
	}

	m_tagList.clear();

	m_reader->startCyclicInventory(timeout);

	QrfeSleeper::MSleepAlive(timeout + 10);

	m_reader->stopCyclicInventory();

	maxReadCount = m_tagList.value(m_tag->tagId());
	infoAppend("->  Tag detected " + QString::number(maxReadCount) + " times");
	showOK();
	return;
}

void CGen2TagPowerReadMeasurement::cyclicInventory(const QrfeGlobal::TagReadEvent& tag)
{
	if(m_reader == 0 || m_tag == 0)
		return;

	m_tagList[tag.tagId]++;
}


void CGen2TagPowerReadMeasurement::exportSweepResults()
{
	if(m_reader == 0 || m_tag == 0)
		return;

	QString path = Cache::d.value(EXPORT_LAST_USED_FILEPATH, QDir::rootPath()).toString();

	QString prefix;
	prefix = "PowerVsReadCount_" + m_tag->tagId() + "_";
	QString fileName = QDir::rootPath() + "/" + prefix + "Results_" + QDateTime::currentDateTime().toString("yyyy_MM_dd-hh_mm");
	QString outputFileName;

	if(ui.tabWidget->currentIndex() == 0)
	{
		if(!QrfeQwt::savePlotToFile(m_freqSweepPlot, m_parent, "Save Plot to File", fileName, outputFileName))
			return;
	}
	else
	{
		if(!QrfeGlobal::saveStandardModelToFile(m_freqSweepValueModel, m_parent, "Save Data to File", fileName, outputFileName))
			return;
	}

	QFileInfo info(outputFileName);
    Cache::d.setValue(EXPORT_LAST_USED_FILEPATH, info.absolutePath());
}


QwtLinearColorMap* CGen2TagPowerReadMeasurement::colorMap()
{
	QwtLinearColorMap* c1 = new QwtLinearColorMap(Qt::white, Qt::darkGreen);
	c1->addColorStop(0.25, Qt::darkRed);
	c1->addColorStop(0.5,  Qt::yellow);
	c1->addColorStop(0.75, Qt::green);
	c1->addColorStop(1.0,  Qt::darkGreen);
	c1->setMode( QwtLinearColorMap::ScaledColors );
	return c1;
}


void CGen2TagPowerReadMeasurement::reloadLicenseData()
{
    ui.startFreqSweepButton->setEnabled(true);
    ui.exportSweepButton->setEnabled(true);
}
