#include "CRfePurStaticReflectedPowerMeasurement.h"

#include <License.h>
#include <Cache.h>

#include <QTimer>

#include <QrfeResourceGlobal>

#include <qwt_dial.h>
#include <qwt_dial_needle.h>

#include <QtCore/qmath.h>

#include <reader/QrfeRfePurReader>
#include <as399x/AS399X_Defines.h>

#include <def.h>

#define CACHE_HEADER		QString("ReaderSettings - CRfePurStaticReflectedPowerMeasurement - ")


class DynamicNeedle : public QwtDialSimpleNeedle
{
public:
	DynamicNeedle() : QwtDialSimpleNeedle(Arrow,true,Qt::blue,Qt::red){}
	double min,max,current;
	virtual void draw (QPainter* painter, const QPoint &center, int length, double direction, QPalette::ColorGroup cg = QPalette::Active) const
	{
		length = (int) (((double)length) * (current-min)/(max-min));
		QwtDialSimpleNeedle::draw(painter,center,length,direction,cg);
	}
protected:
	virtual void drawNeedle (QPainter* painter, double length, QPalette::ColorGroup cg = QPalette::Active) const
	{
		length = (int) (((double)length) * (current-min)/(max-min));
		QwtDialSimpleNeedle::drawNeedle(painter,length,cg);
	}
};


CRfePurStaticReflectedPowerMeasurement::CRfePurStaticReflectedPowerMeasurement(QTextEdit* infoEdit, QWidget* parent)
    : ReaderTabWidget(tr("Reflected Power Measurement"), parent)
    , m_reader(0)
{
	ui.setupUi(this);
	setInfoEdit(infoEdit);

	connect(ui.rfpStartButton, 				SIGNAL(clicked()),
			this, 							  SLOT(startStopRfpMeasurement()));

	connect(ui.attenuationSlider, 			SIGNAL(valueChanged(int)),
			this, 							  SLOT(setAttenuationLabel(int)));

	m_rfpMeasurementNeedle = new DynamicNeedle();
	m_rfpMeasurementNeedle->max = 20.0;
	m_rfpMeasurementNeedle->min = 0.0;
	m_rfpMeasurementDial = new QwtDial(this);
	m_rfpMeasurementDial->setNeedle(m_rfpMeasurementNeedle);
	m_rfpMeasurementDial->setReadOnly(true);
	m_rfpMeasurementDial->setWrapping(true);
	m_rfpMeasurementDial->setOrigin(0);

    //**TODO** Check
    //m_rfpMeasurementDial->setDirection(QwtDial::CounterClockwise);
	ui.rfpMeasurementNeedleLayout->addWidget(m_rfpMeasurementDial);

	m_reader 	= 0;

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

CRfePurStaticReflectedPowerMeasurement::~CRfePurStaticReflectedPowerMeasurement()
{

}

bool CRfePurStaticReflectedPowerMeasurement::init(QrfeReaderInterface* reader)
{
	m_reader = qobject_cast<QrfeRfePurReader*>(reader);
	if( m_reader == 0 )
		return false;

	ui.rfpSignalIBar->setValue(0);
	ui.rfpSignalILabel->setText("");
	ui.rfpSignalQBar->setValue(0);
	ui.rfpSignalQLabel->setText("");
	ui.rfpBar->setValue(0);
	ui.rfpLabel->setText("0 dBm");
	ui.rfpStartButton->setText("Start");
	ui.rfpStartButton->setIcon(QIcon(QrfeGlobal::getButtonIconResourcePath("start")));
	m_rfpMeasurementActive = false;
	m_rfpMeasurementNeedle->current = 0;
	m_rfpMeasurementDial->repaint();

	ushort maxAtt = 0, currentAtt = 0;
	if(m_reader->getMaxAttenuation(maxAtt) == QrfeGlobal::RES_OK)
		ui.attenuationSlider->setMaximum(maxAtt);

	if(m_reader->getCurrentAttenuation(currentAtt) == QrfeGlobal::RES_OK){
		ui.attenuationSlider->setValue(currentAtt);
		setAttenuationLabel(currentAtt);
	}

	ui.antennaComboBox->clear();
	for(int i = 0; i < m_reader->antennaCount(); i++)
	{
		ui.antennaComboBox->addItem("Antenna #" + QString::number(i+1));
	}
	ui.antennaComboBox->setCurrentIndex(0);

	reloadLicenseData();
    loadValuesFromCache();

	return true;
}

void CRfePurStaticReflectedPowerMeasurement::deinit()
{
	m_reader 	= 0;
}

void CRfePurStaticReflectedPowerMeasurement::activated()
{
	if(m_reader == 0)
		return;

	ushort currentAtt;
	if(m_reader->getCurrentAttenuation(currentAtt) == QrfeGlobal::RES_OK)
	{
		ui.attenuationSlider->setValue(currentAtt);
		setAttenuationLabel(currentAtt);
		infoSet("-- The current Attenuation is " + ui.attenuationLabel->text() + " --");
	}
	else
	{
		infoSet("-- Could not read current attenuation --");
		showNOK();
		return;
	}

	showOK();
}

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


void CRfePurStaticReflectedPowerMeasurement::startStopRfpMeasurement()
{
	if(!m_rfpMeasurementActive)
	{
		ulong freq = ui.rfpTestFreqSpinBox->value() * 1000;
		QString freqStr = ui.rfpTestFreqSpinBox->text();

		if(m_reader->setWorkingAntenna(ui.antennaComboBox->currentIndex() + 1) != QrfeGlobal::RES_OK)
		{
			infoSetError("-- Could not select " + ui.antennaComboBox->currentText() + " --");
			return;
		}

		if(m_reader->setTestFrequency(freq) != QrfeGlobal::RES_OK)
		{
			infoSetError("-- Could not set test frequency to " + freqStr + "MHz --");
			return;
		}

		if(m_reader->setAttenuation(ui.attenuationSlider->value()) != QrfeGlobal::RES_OK)
		{
			infoSetError("-- Could not set Attenuation to " + ui.attenuationLabel->text() + " --");

			ushort current;
			if(m_reader->getCurrentAttenuation(current) == QrfeGlobal::RES_OK)
			{
				ui.attenuationSlider->setValue(current);
				infoAppend("-- The current Attenuation is " + ui.attenuationLabel->text() + " --");
			}
			else
			{
				infoAppend("-- Could not get Attenuation --");
				return;
			}
		}

		m_rfpMeasurementActive = true;

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

		ui.attenuationSlider->setEnabled(false);
		ui.antennaComboBox->setEnabled(false);

		QTimer::singleShot(50, this, SLOT(measureReflectedPower()));
		License::d->decrementExecutionCount(this);
        saveValuesToCache();
		setWorking();
	}
	else
	{
		m_rfpMeasurementActive = false;

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

		ui.attenuationSlider->setEnabled(true);
		ui.antennaComboBox->setEnabled(true);
	}
}


void CRfePurStaticReflectedPowerMeasurement::measureReflectedPower()
{
	char chI, chQ;
	uchar G;
	ulong freq = ui.rfpTestFreqSpinBox->value() * 1000;
	ushort time = ui.timeoutBox->value();
	QrfeGlobal::Result res = m_reader->measureReflectedPower(freq, time, chI, chQ, G);
	if(res == QrfeGlobal::RES_OK)
	{
		ui.rfpSignalIBar->setValue((int)chI + 128);
		ui.rfpSignalILabel->setText(QString::number((int)chI));
		ui.rfpSignalQBar->setValue((int)chQ + 128);
		ui.rfpSignalQLabel->setText(QString::number((int)chQ));

		if(G != 0)
		{
			double offset = 20*log10(0.5/G);
			if(offset < 0)
				offset *= -1;
			ui.rfpBar->setMaximum(20 + offset);
			ui.rfpBar->setMinimum(0);

			double dBm, i, q, angle;
			i = chI;
			q = chQ;
			dBm = sqrt( (i*i) + (q*q) );
			if (dBm == 0) dBm = 0.5;
			dBm = 20*log10(dBm/G);
			angle = atan2(q,i);
			if (angle < 0 )
				angle += 2 * M_PI;
			angle = (angle / (2*M_PI)) *360.0;

			ui.rfpBar->setValue(dBm + offset);
			ui.rfpLabel->setText(QString::number(dBm) + " dBm");
			m_rfpMeasurementNeedle->current = dBm;
			m_rfpMeasurementNeedle->min = 20*log10(0.5/G);
			m_rfpMeasurementDial->setValue(angle);
			m_rfpMeasurementDial->repaint();

			infoSetOK("-- Measured reflected power ( " + QString::number((int)chI) + ", " + QString::number((int)chQ) + " ) --");
			infoAppend(QString("Calced %1 with a G of %2 / Showing with offset of %3").arg(dBm).arg(G).arg(offset));
		}
	}
	else {
		infoSetError("-- Could measure reflected power --");
	}

	if(m_rfpMeasurementActive)
		QTimer::singleShot(50, this, SLOT(measureReflectedPower()));
	else
	{
		reloadLicenseData();
		setIdle();
	}
}

void CRfePurStaticReflectedPowerMeasurement::reloadLicenseData()
{
    ui.rfpStartButton->setEnabled(true);
}


void CRfePurStaticReflectedPowerMeasurement::setAttenuationLabel ( int value )
{
	ui.attenuationLabel->setText(QString::number(value) + " steps");
}

void CRfePurStaticReflectedPowerMeasurement::loadValuesFromCache()
{
    ui.rfpTestFreqSpinBox->setValue( Cache::d.value(CACHE_HEADER + "TestFrequency", 866.0).toDouble() );
    ui.timeoutBox->setValue( Cache::d.value(CACHE_HEADER + "Timeout", 1).toUInt() );
    ui.attenuationSlider->setValue( Cache::d.value(CACHE_HEADER + "Attenuation", 19).toUInt() );
    ui.antennaComboBox->setCurrentIndex( Cache::d.value(CACHE_HEADER + "Antenna", 0).toUInt() );
}

void CRfePurStaticReflectedPowerMeasurement::saveValuesToCache()
{
    Cache::d.setValue(CACHE_HEADER + "TestFrequency", ui.rfpTestFreqSpinBox->value() );
    Cache::d.setValue(CACHE_HEADER + "Timeout", ui.timeoutBox->value() );
    Cache::d.setValue(CACHE_HEADER + "Attenuation", ui.attenuationSlider->value() );
    Cache::d.setValue(CACHE_HEADER + "Antenna", ui.antennaComboBox->currentIndex() );
}
