#include "CRfePurDebugWindow.h"

#include <reader/QrfeRfePurReader>

#include "../../application/Application.h"
#include "../../application/Reader.h"

#include <qwt_plot.h>
#include <qwt_plot_histogram.h>
#include <qwt_legend.h>
#include <qwt_scale_draw.h>

#include <QrfeGuiLibGlobal>
#include <QrfeResourceGlobal>

typedef enum {
	COL_ReaderId = 0,
	COL_Frequency = 1,
	COL_RSSI = 2,
	COL_Antenna = 3,
} COL_IDs;

class AntennaPowerScaleDraw: public QwtScaleDraw
{
public:
	AntennaPowerScaleDraw()
    {
		setTickLength(QwtScaleDiv::MajorTick, 4.0);
		setTickLength(QwtScaleDiv::MediumTick, 0);
		setTickLength(QwtScaleDiv::MinorTick, 0);
        setLabelAlignment( Qt::AlignLeft | Qt::AlignVCenter );

        //setLabelRotation( 15.0 );
        setSpacing( 8.0 );
    }

    virtual QwtText label( double value ) const
    {
        if(value == 2)
                return QwtText("ON");
        else if(value == 1)
                return QwtText("OFF");
        return QwtText("");
    }
};

CRfePurDebugWindow::CRfePurDebugWindow(Application* app, QWidget *parent)
    : QWidget(parent)
	, QrfeTraceModule("CRfePurDebugWindow")
	, m_application(app)
{
	ui.setupUi(this);

	m_frequencyPlot = new QwtPlot(this);
	m_frequencyPlot->setAxisTitle(QwtPlot::xBottom, "Frequency (MHz)");
	m_frequencyPlot->setAxisScale(0, 	0.0, 2.0);
	m_frequencyPlot->setAxisScaleDraw( QwtPlot::yLeft, new AntennaPowerScaleDraw() );
	m_frequencyPlot->setAxisScale(2, 	864.0, 869.0);

//    QwtLegend *legend = new QwtLegend;
//    legend->setItemMode(QwtLegend::CheckableItem);
//    m_frequencyPlot->insertLegend(legend, QwtPlot::RightLegend);


	ui.frequencyPlotLayout->addWidget(m_frequencyPlot);

	ui.frequencyTableView->setModel(&m_frequencyModel);

	this->setVisible(false);

	connect(m_application, 		SIGNAL(readerAttached(Reader*)),
			this, 				  SLOT(readerChanged()) );
	connect(m_application, 		SIGNAL(readerLost()),
			this, 				  SLOT(readerChanged()) );
}

CRfePurDebugWindow::~CRfePurDebugWindow()
{
	delete m_frequencyPlot;
}

void CRfePurDebugWindow::showEvent ( QShowEvent * event )
{
	loadReader();
	QWidget::showEvent(event);
}

void CRfePurDebugWindow::hideEvent ( QHideEvent * event )
{
	unloadReader();
	QWidget::hideEvent(event);
}

void CRfePurDebugWindow::readerChanged()
{
	if(isVisible())
	{
		unloadReader();
		loadReader();
	}
}

void CRfePurDebugWindow::notification ( uchar id, const QVariant& value )
{
	QrfeRfePurReader* reader = qobject_cast<QrfeRfePurReader*>(sender());
	if(reader == 0)
		return;

	QString readerId = reader->readerId();

	switch(id)
	{
	case QrfeRfePurReader::NOTIFICATION_ID_ANTENNA_POWER_CHANGED:
		m_frequencyData[readerId].antennaState = value.toBool();
		break;
	case QrfeRfePurReader::NOTIFICATION_ID_FREQUENCY_CHANGED:
		m_frequencyData[readerId].frequency = ((double)value.toUInt()) / 1000.0;
		break;
	case QrfeRfePurReader::NOTIFICATION_ID_LBT_RSSI_VALUE_MEASURED:
		m_frequencyData[readerId].rssi = ((short)value.toInt());
		break;
	}

	updateReaderFrequEntry(readerId);
	checkForCollision();
}

void CRfePurDebugWindow::loadReader()
{
	m_readerList.clear();
	m_frequencyHistograms.clear();
	m_frequencyModel.clear();
	m_frequencyModelReaderIndex.clear();

	m_frequencyModel.setColumnCount(4);
	m_frequencyModel.setHorizontalHeaderLabels(QStringList() << "Reader" << "Frequency" << "Last RSSI" << "Antenna");
	ui.frequencyTableView->setColumnWidth(COL_ReaderId, 	230);
	ui.frequencyTableView->setColumnWidth(COL_Frequency, 	70);
	ui.frequencyTableView->setColumnWidth(COL_RSSI, 		70);
	ui.frequencyTableView->setColumnWidth(COL_Antenna, 		70);

	QList<QString> readers = m_application->readerList();
	foreach(QString readerId, readers)
	{
		QrfeReaderInterface* interface = m_application->reader(readerId)->readerInterface();
		QrfeRfePurReader* purReader = qobject_cast<QrfeRfePurReader*>(interface);
		if(purReader != 0)
			m_readerList << purReader;
	}

	int index = 0;
	foreach(QrfeRfePurReader* purReader, m_readerList)
	{
		QColor color = QrfeGlobal::getAlternatingDarkColors(index++);

		QwtPlotHistogram* frequHistogram = new QwtPlotHistogram("[" + purReader->name() + "]");
		setHistoColor(frequHistogram, color);
		frequHistogram->attach(m_frequencyPlot);
	    m_frequencyHistograms.insert(purReader->readerId(), frequHistogram);

		m_frequencyModelReaderIndex << purReader->readerId();
		m_frequencyModel.appendRow(QList<QStandardItem*>() << new QStandardItem(purReader->name()) << new QStandardItem("") << new QStandardItem("") << new QStandardItem(""));
		
		QFont f = m_frequencyModel.item(m_frequencyModelReaderIndex.indexOf(purReader->readerId()), 0)->font();
		f.setBold(true);
		m_frequencyModel.item(m_frequencyModelReaderIndex.indexOf(purReader->readerId()), COL_ReaderId)->setFont(f);

		m_frequencyModel.item(m_frequencyModelReaderIndex.indexOf(purReader->readerId()), COL_Frequency)->setTextAlignment(Qt::AlignCenter);
		m_frequencyModel.item(m_frequencyModelReaderIndex.indexOf(purReader->readerId()), COL_RSSI)->setTextAlignment(Qt::AlignCenter);
		m_frequencyModel.item(m_frequencyModelReaderIndex.indexOf(purReader->readerId()), COL_Antenna)->setTextAlignment(Qt::AlignCenter);

		m_frequencyModel.item(m_frequencyModelReaderIndex.indexOf(purReader->readerId()), COL_ReaderId)->setForeground(Qt::white);
		m_frequencyModel.item(m_frequencyModelReaderIndex.indexOf(purReader->readerId()), COL_Frequency)->setForeground(Qt::white);
		m_frequencyModel.item(m_frequencyModelReaderIndex.indexOf(purReader->readerId()), COL_RSSI)->setForeground(Qt::white);
		m_frequencyModel.item(m_frequencyModelReaderIndex.indexOf(purReader->readerId()), COL_Antenna)->setForeground(Qt::white);

		m_frequencyModel.item(m_frequencyModelReaderIndex.indexOf(purReader->readerId()), COL_ReaderId)->setBackground(color);
		m_frequencyModel.item(m_frequencyModelReaderIndex.indexOf(purReader->readerId()), COL_Frequency)->setBackground(color);
		m_frequencyModel.item(m_frequencyModelReaderIndex.indexOf(purReader->readerId()), COL_RSSI)->setBackground(color);
		m_frequencyModel.item(m_frequencyModelReaderIndex.indexOf(purReader->readerId()), COL_Antenna)->setBackground(color);

	    purReader->activateNotification(QrfeRfePurReader::NOTIFICATION_ID_ANTENNA_POWER_CHANGED);
	    purReader->activateNotification(QrfeRfePurReader::NOTIFICATION_ID_FREQUENCY_CHANGED);
        purReader->activateNotification(QrfeRfePurReader::NOTIFICATION_ID_LBT_RSSI_VALUE_MEASURED);
        purReader->activateNotification(QrfeRfePurReader::NOTIFICATION_ID_ANTENNA_RFP_VALUE_MEASURED);

		connect(purReader, SIGNAL(notification ( uchar, const QVariant&)),
				this, 	    SLOT(notification ( uchar, const QVariant&)));
	}
}

void CRfePurDebugWindow::unloadReader()
{
	foreach(QrfeRfePurReader* purReader, m_readerList)
	{
	    purReader->deactivateNotification(QrfeRfePurReader::NOTIFICATION_ID_ANTENNA_POWER_CHANGED);
	    purReader->deactivateNotification(QrfeRfePurReader::NOTIFICATION_ID_FREQUENCY_CHANGED);
	    purReader->deactivateNotification(QrfeRfePurReader::NOTIFICATION_ID_LBT_RSSI_VALUE_MEASURED);
        purReader->deactivateNotification(QrfeRfePurReader::NOTIFICATION_ID_ANTENNA_RFP_VALUE_MEASURED);

	    m_frequencyHistograms.value(purReader->readerId())->detach();
	    delete m_frequencyHistograms.value(purReader->readerId());

		disconnect( purReader, SIGNAL(notification ( uchar, const QVariant&)),
					this, 		SLOT(notification ( uchar, const QVariant&)));
	}

	m_readerList.clear();
	m_frequencyHistograms.clear();
	m_frequencyModel.clear();
	m_frequencyModelReaderIndex.clear();
}



void CRfePurDebugWindow::setHistoColor(QwtPlotHistogram* histo, const QColor &symbolColor)
{
    QColor color = symbolColor;
    color.setAlpha(180);

    histo->setPen(QPen(Qt::black));
    histo->setBrush(QBrush(color));

    QwtColumnSymbol *symbol = new QwtColumnSymbol(QwtColumnSymbol::Box);
    symbol->setFrameStyle(QwtColumnSymbol::Raised);
    symbol->setLineWidth(2);
    symbol->setPalette(QPalette(color));
    histo->setSymbol(symbol);
}

void CRfePurDebugWindow::updateReaderFrequEntry(QString readerId)
{
	bool on 	= m_frequencyData.value(readerId).antennaState;
	double freq = m_frequencyData.value(readerId).frequency;
	short rssi 	= m_frequencyData.value(readerId).rssi;

	trc(5, "Reader " + readerId + " on freq " + QString::number(freq) + " is " + ((on)?"ON":"OFF"));

	m_frequencyModel.item(m_frequencyModelReaderIndex.indexOf(readerId), COL_Frequency)->setText(QString::number(freq));
	m_frequencyModel.item(m_frequencyModelReaderIndex.indexOf(readerId), COL_Antenna)->setText(QString::number(rssi));

	m_frequencyModel.item(m_frequencyModelReaderIndex.indexOf(readerId), COL_Antenna)->setText(((on)?"ON":"OFF"));
	if(on){
		m_frequencyModel.item(m_frequencyModelReaderIndex.indexOf(readerId), COL_Antenna)->setIcon(QIcon(":/icons/redLED_on"));
	}else{
		m_frequencyModel.item(m_frequencyModelReaderIndex.indexOf(readerId), COL_Antenna)->setIcon(QIcon(":/icons/redLED_off"));
	}

	double min = freq - ui.collisionWindowSpinBox->value();
	double max = freq + ui.collisionWindowSpinBox->value();
	QwtInterval interval(min , max);
	QVector<QwtIntervalSample> samples;
	samples.append(QwtIntervalSample((on)?2:1, interval));
	m_frequencyHistograms.value(readerId)->setSamples(samples);
	m_frequencyHistograms.value(readerId)->show();
	m_frequencyPlot->replot();

}

void CRfePurDebugWindow::checkForCollision()
{
	QList<double> usedFreqs;
	bool collision = false;
	foreach(QString readerId, m_frequencyData.keys())
	{
		if(m_frequencyData.value(readerId).antennaState == true)
		{
			double readerFreq = m_frequencyData.value(readerId).frequency;
			double diff =  ui.collisionWindowSpinBox->value();
			foreach(double freq, usedFreqs)
			{
				if( ((readerFreq - diff) > (freq - diff) && (readerFreq - diff) < (freq + diff)) ||
					((readerFreq + diff) > (freq - diff) && (readerFreq + diff) < (freq + diff)) )
					collision = true;
			}

			if(collision)
				break;

			usedFreqs << readerFreq;
		}
	}

	if(collision)
	{
		warning("Detected Collision with following setup:");
		foreach(QString readerId, m_frequencyData.keys())
		{
			warning("  Reader " + readerId + " on freq " + QString::number(m_frequencyData.value(readerId).frequency) +
					" is " + ((m_frequencyData.value(readerId).antennaState)?"ON":"OFF"));
		}
	}

	if(collision){
		ui.collisionLabel->setText("ERROR");
		ui.collisionIconLabel->setPixmap(QrfeGlobal::getButtonIconResourcePath("error"));
	}
	else{
		ui.collisionLabel->setText("OK");
		ui.collisionIconLabel->setPixmap(QrfeGlobal::getButtonIconResourcePath("ok"));
	}
}

