/*
 * Reader.cpp
 *
 *  Created on: 18.07.2011
 *      Author: stefan.detter
 */

#include "Reader.h"

int Reader::m_instanceCount = 0;

Reader::Reader(QrfeReaderInterface* reader, QObject* parent)
	: QObject(parent)
	, QrfeTraceModule("Reader")
	, m_reader(reader)
{
	initInstance();
	trc(1, "Creating. Count: " + QString::number(++m_instanceCount));
}

Reader::~Reader()
{
	trc(1, "Destroying. Count: " + QString::number(--m_instanceCount));
}

Pipe* Reader::pipe()
{
	return 0;
}

QrfeReaderInterface* Reader::readerInterface()
{
	return m_reader;
}

QString 					Reader::name() const								{return m_reader->name() ;}
QString 					Reader::readerId() const							{return m_reader->readerId() ;}
QString 					Reader::serialNumber() const						{return m_reader->serialNumber() ;}
ulong 						Reader::serialNumberExact() const					{return m_reader->serialNumberExact() ;}
QrfeGlobal::ReaderType		Reader::readerType() const							{return m_reader->readerType() ;}
ulong 						Reader::readerTypeExact() const						{return m_reader->readerTypeExact() ;}
QString						Reader::readerTypeExactString() const				{return m_reader->readerTypeExactString() ;}
QrfeGlobal::ReaderModule	Reader::readerModule() const						{return m_reader->readerModule() ;}
QString						Reader::readerModuleString() const					{return m_reader->readerModuleString() ;}
QrfeGlobal::TagType			Reader::tagType() const								{return m_reader->tagType() ;}
QString 					Reader::tagTypeString() const						{return m_reader->tagTypeString() ;}
ulong 						Reader::hardwareRevision() const					{return m_reader->hardwareRevision() ;}
QString 					Reader::hardwareRevisionString() const				{return m_reader->hardwareRevisionString() ;}
ulong 						Reader::softwareRevision() const					{return m_reader->softwareRevision() ;}
QString						Reader::softwareRevisionString() const				{return m_reader->softwareRevisionString() ;}
QString 					Reader::advancedSoftwareRevisionString() const		{return "Date: " + m_reader->buildDate() + "\n" +
																						"Time: " + m_reader->buildTime() + "\n" +
																						"Rev:  " + m_reader->buildRevision();}
ulong 						Reader::bootloaderRevision() const					{return m_reader->bootloaderRevision() ;}
QString						Reader::bootloaderRevisionString() const			{return m_reader->bootloaderRevisionString() ;}
QrfeGlobal::HandlerState 	Reader::currentState() const						{return m_reader->currentState() ;}
QString 					Reader::currentStateString() const					{return m_reader->currentStateString() ;}
QrfeGlobal::HandlerAction 	Reader::currentAction() const						{return m_reader->currentAction() ;}
QString 					Reader::currentActionString() const					{return m_reader->currentActionString() ;}
QrfeGlobal::ReaderSystem	Reader::currentSystem() const						{return m_reader->currentSystem() ;}
QString						Reader::currentSystemString() const					{return m_reader->currentSystemString() ;}
qulonglong					Reader::statusRegister() const						{return m_reader->statusRegister() ;}
QStringList					Reader::statusRegisterBitDescriptions() const		{return m_reader->statusRegisterBitDescriptions() ;}
ulong 						Reader::gpioValues() const 							{return m_reader->gpioValues() ;}
uchar 						Reader::antennaCount() const						{return m_reader->antennaCount() ;}
QString						Reader::deviceName() const							{return m_reader->deviceName() ;}
QrfeGlobal::DeviceType		Reader::deviceType() const							{return m_reader->deviceType() ;}
ulong  						Reader::readerCaps() const							{return m_reader->readerCaps() ;}
ulong  						Reader::tagFunctionCaps() const						{return m_reader->tagFunctionCaps() ;}
QString 					Reader::readerName() const							{return m_reader->readerName() ;}
QString 					Reader::readerLocation() const						{return m_reader->readerLocation(); }
QrfeGlobal::Result 			Reader::readSettings( )								{return m_reader->readSettings(); }
void 						Reader::destroy()									{this->deleteLater(); return m_reader->destroy();}



void Reader::startPipe (  )
{
    emit inventoryAboutToStart();

	m_reader->startCyclicInventory();
    emit inventoryStarted();
}

void Reader::stopPipe ( )
{
	m_reader->stopCyclicInventory();
    emit inventoryStoped();
}

void Reader::pausePipe (  )
{
    m_reader->stopCyclicInventory();
    emit inventoryPaused();
}

void Reader::continuePipe (  )
{
    m_reader->startCyclicInventory();
    emit inventoryContinued();
}

void Reader::initInstance()
{
	connect(m_reader, 		SIGNAL( heartBeat() ),
			this, 			SIGNAL( heartBeat() ), Qt::DirectConnection );
	connect(m_reader, 		SIGNAL( notification ( uchar, const QVariant&) ),
			this, 			  SLOT( notificationSlot ( uchar, const QVariant&) ), Qt::DirectConnection );
    connect(m_reader, 		SIGNAL( signatureChanged() ),
            this, 			SIGNAL( signatureChanged() ), Qt::DirectConnection );
    connect(m_reader, 		SIGNAL( tagTypeChanged(int) ),
            this, 			SIGNAL( tagTypeChanged(int) ), Qt::DirectConnection );
    connect(m_reader, 		SIGNAL( changedState(int) ),
			this, 			SIGNAL( changedState(int) ), Qt::DirectConnection );
	connect(m_reader, 		SIGNAL( changedAction(int) ),
			this, 			SIGNAL( changedAction(int) ), Qt::DirectConnection );
	connect(m_reader, 		SIGNAL( changedStatusRegister(qulonglong) ),
			this, 			SIGNAL( changedStatusRegister(qulonglong) ), Qt::DirectConnection );
	connect(m_reader, 		SIGNAL( changedGpioValues(ulong) ),
			this, 			SIGNAL( changedGpioValues(ulong) ), Qt::DirectConnection );
	connect(m_reader, 		SIGNAL( changedRssiEnable(bool, uchar, const QStringList&, int, int) ),
			this, 			SIGNAL( changedRssiEnable(bool, uchar, const QStringList&, int, int) ), Qt::DirectConnection );
	connect(m_reader, 		SIGNAL( changedReadFrequencyEnable(bool) ),
			this, 			SIGNAL( changedReadFrequencyEnable(bool) ), Qt::DirectConnection );
	connect(m_reader, 		SIGNAL( changedReaderName(const QString&) ),
			this, 			SIGNAL( changedReaderName(const QString&) ), Qt::DirectConnection );
	connect(m_reader, 		SIGNAL( changedReaderLocation(const QString&) ),
			this, 			SIGNAL( changedReaderLocation(const QString&) ), Qt::DirectConnection );
	connect(m_reader, 		SIGNAL( requestForDelete() ),
			this, 			SIGNAL( requestForDelete() ), Qt::DirectConnection );
	connect(m_reader, 		SIGNAL( lostConnection() ),
			this, 			SIGNAL( lostConnection() ), Qt::DirectConnection );
	connect(m_reader, 		SIGNAL( lostConnection() ),
			this, 			SIGNAL( lostConnection() ), Qt::DirectConnection );

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

	m_reader->getRSSIChannels(m_rssiChannelName, m_rssiChannelMinimum, m_rssiChannelMaximum, m_rssiChannelUnits);
}


void Reader::notificationSlot ( uchar id, const QVariant& value )
{
    emit notification(id, m_reader->getNotificationName(id), value);
}


#include <QrfeReaderInterfaceGlobal>
#include <tagId/QrfeGS1TagIdFactory>

void Reader::cyclicInventorySlot(const QrfeGlobal::TagReadEvent& tag)
{
	TagEvent event( m_reader->serialNumber(), m_reader->readerName(), m_reader->readerLocation(),
					m_reader->tagTypeString(), m_reader->tagType(), tag.tagId, tag.tagIdBytes );

    if(m_reader->tagType() == QrfeGlobal::TAG_GEN2 || m_reader->tagType() == QrfeGlobal::TAG_GEN2_NXP_READPROTECTED)
        event.setVisualTagId(QrfeGS1TagIdFactory::getTagIdString(tag.tagIdBytes));

    if(tag.hasRSSI && tag.rssiPercent.size() == m_rssiChannelName.size() + 1)
    {
        RSSI_Information rssi(tag.rssiPercent.at(0));
        for(int i = 0; i < m_rssiChannelName.size(); i++)
            rssi.addChannel(m_rssiChannelName.at(i), m_rssiChannelMinimum.at(i), m_rssiChannelMaximum.at(i), (long)tag.rssiPercent.at(i+1), m_rssiChannelUnits.at(i));

        QVariant v;
        v.setValue(rssi);
        event.addInformation(RSSI_Information::id, v);
    }

    if(tag.hasTrigger)
    {
        TRIGGER_Information trigger(tag.triggerSourceId, tag.triggerSource);

        QVariant v;
        v.setValue(trigger);
        event.addInformation(TRIGGER_Information::id, v);
    }

    if(tag.hasMemory)
    {
        MEMORY_Information memory("", tag.memBank, tag.memAddr, tag.memData);

        QVariant v;
        v.setValue(memory);
        event.addInformation(MEMORY_Information::id, v);
    }

    if(tag.hasAntenna)
    {
        ANTENNA_Information antenna(tag.antennaId);

        QVariant v;
        v.setValue(antenna);
        event.addInformation(ANTENNA_Information::id, v);
    }

    if(tag.hasReadFrequency)
    {
        FREQUENCY_Information frequency(tag.readFrequency);

        QVariant v;
        v.setValue(frequency);
        event.addInformation(FREQUENCY_Information::id, v);
    }

    if(tag.hasHandle)
    {
        HANDLE_Information handle(tag.handle);

        QVariant v;
        v.setValue(handle);
        event.addInformation(HANDLE_Information::id, v);
    }

    if(tag.hasState)
    {
        STATE_Information state(tag.state, tag.stateName);

        QVariant v;
        v.setValue(state);
        event.addInformation(STATE_Information::id, v);
    }

    if(tag.hasBattery)
    {
        BATTERY_Information battery(tag.battery);

        QVariant v;
        v.setValue(battery);
        event.addInformation(BATTERY_Information::id, v);
    }

    if(tag.hasPC)
    {
        PC_Information pc(tag.pc);

        QVariant v;
        v.setValue(pc);
        event.addInformation(PC_Information::id, v);
    }

    if(tag.hasMessageId)
    {
        MESSAGEID_Information messageId(tag.messageId);

        QVariant v;
        v.setValue(messageId);
        event.addInformation(MESSAGEID_Information::id, v);
    }

    if(tag.hasRN16)
    {
        RN16_Information rn16(tag.rn16);

        QVariant v;
        v.setValue(rn16);
        event.addInformation(RN16_Information::id, v);
    }

    if(tag.hasNxpBrandId)
    {
        NXP_BRANDID_Information nxpBrand(tag.nxpBrandId);

        QVariant v;
        v.setValue(nxpBrand);
        event.addInformation(NXP_BRANDID_Information::id, v);
    }

    if(tag.hasApplicationInfo)
    {
        QMap<uint,QPair<QString,QString> > genericInfo;
        m_reader->getApplicationInformation(tag.applicationInfo, genericInfo);

        for(int i = 0; i < genericInfo.keys().size(); i++)
        {
            QPair<QString,QString> info = genericInfo.value(genericInfo.keys().at(i));
            GENERIC_Information genInfo(genericInfo.keys().at(i), info.first, info.second);

            QVariant v;
            v.setValue(genInfo);
            event.addInformation(GENERIC_Information::id, v);
        }
    }

	emit tagEvent(event);
}
