/*
 * QrfeProtocollHandlerRFE.h
 *
 *  Created on: 15.01.2009
 *      Author: stefan.detter
 */

#ifndef QRFEPROTOCOLLHANDLERRFE_H_
#define QRFEPROTOCOLLHANDLERRFE_H_

#include <QrfeProtocolHandler.h>
#include <QrfeProtocolHandlerRFE_Defines.h>

#include <QMutex>
#include <QMap>
#include <QTimer>
#include <QPair>

#include <QrfeTrace>
#include <QrfeProtocolHandlerGlobal>


class QrfeProtocolHandlerRFE : public QrfeProtocolHandler
{
	Q_OBJECT

public:
	QrfeProtocolHandlerRFE(QIODevice* dev, QrfeGlobal::DeviceType deviceType, QObject* parent = 0);
	virtual ~QrfeProtocolHandlerRFE();

public:
	eRFE_RET_VALUE	lastReturnCode();

	void useDeprecatedRfFunctions ( bool use );

	QrfeGlobal::Result getReaderID ( ulong &readerID );
	QrfeGlobal::Result getReaderType ( ulong &readerType );
	QrfeGlobal::Result getHardwareRevision ( ulong &hardwareRevision );
	QrfeGlobal::Result getSoftwareRevision ( ulong &softwareRevision );
	QrfeGlobal::Result getBootloaderRevision ( ulong &bootloaderRevision );
	QrfeGlobal::Result getCurrentSystem ( QString &currentSystem );
	QrfeGlobal::Result getCurrentState ( QrfeGlobal::ReaderState &currentState );
	QrfeGlobal::Result getStatusRegister ( qulonglong &statusRegister );
	QrfeGlobal::Result getAntennaCount ( uchar &count );

	QrfeGlobal::Result getDeviceName ( QString &name );
	QrfeGlobal::Result setDeviceName ( const QString &name );
	QrfeGlobal::Result getDeviceLocation ( QString &name );
	QrfeGlobal::Result setDeviceLocation ( const QString &location );

	QrfeGlobal::Result getAttenuation ( ushort &maxAttenuation, ushort &attenuation );
	QrfeGlobal::Result getFrequency ( uchar &mode, uchar &maxFrequencyCount, QList<uint> &frequencies );
	QrfeGlobal::Result getSensitivity ( short &maxSensitivity, short &minSensitivity, short &currentSensitivity );
	QrfeGlobal::Result getLbtParams ( ushort &listenTime, ushort &idleTime, ushort &maxAllocTime, short &rssiThreshold );
	QrfeGlobal::Result setAttenuation ( ushort value );
	QrfeGlobal::Result setFrequency ( uchar mode, const QList<uint> & frequencies );
	QrfeGlobal::Result setSensitivity ( short targetValue, short &actualValue );
	QrfeGlobal::Result setLbtParams ( ushort listenTime, ushort idleTime, ushort maxAllocTime, short rssiThreshold );

	QrfeGlobal::Result reboot ( );
	QrfeGlobal::Result setHeartBeat ( eRFE_HEARTBEAT_TYPE type, ushort interval = 250 );
	QrfeGlobal::Result setAntennaPower ( bool on );

	QrfeGlobal::Result switchCommBaudrate ( ulong baudrate );
	QrfeGlobal::Result switchCommInterface ( eRFE_COMM_INTERFACE_ID id );
	QrfeGlobal::Result switchSystem ( );
    QrfeGlobal::Result bootloader ( QByteArray &getMessage, QByteArray setMessage );
    QrfeGlobal::Result bootloader ( QByteArray setMessage );

	QrfeGlobal::Result saveSettingsPermanent ( );
	QrfeGlobal::Result restoreFactorySettings ( );

	QrfeGlobal::Result getParam ( ushort address, QByteArray &value );
	QrfeGlobal::Result setParam ( ushort address, QByteArray value );

	QrfeGlobal::Result setTagType(uint type);

	QrfeGlobal::Result getGPIOCaps ( ulong &mask, ulong &output, ulong &input );
	QrfeGlobal::Result getGPIODirection ( ulong &direction );
	QrfeGlobal::Result setGPIODirection ( ulong direction );
	QrfeGlobal::Result getGPIO ( ulong &mask );
	QrfeGlobal::Result setGPIO ( ulong mask );
	QrfeGlobal::Result clearGPIO ( ulong mask );
	QrfeGlobal::Result clearSetGPIO ( ulong clearMask, ulong setMask );

	QrfeGlobal::Result setAntennaSequence ( const QList<QPair<uchar,ulong> > & sequence);
	QrfeGlobal::Result getAntennaSequence ( QList<QPair<uchar,ulong> > & sequence );
	QrfeGlobal::Result setWorkingAntenna ( uchar antennaIndex);
	QrfeGlobal::Result getWorkingAntenna ( uchar & antennaIndex);

	QrfeGlobal::Result activateNotification ( uchar id );
	QrfeGlobal::Result deactivateNotification ( uchar id );
	QrfeGlobal::Result getActiveNotifications ( qulonglong &notifications );

    QrfeGlobal::Result applicationCommand ( const QByteArray& payload );
    QrfeGlobal::Result applicationCommand ( const QByteArray& payload, QByteArray& resp );

	QrfeGlobal::Result doSingleInventory ( QList<QrfeGlobal::TagEvent> &tagList );

	QrfeGlobal::Result setCyclicInventory ( bool on, ulong time = 0 );

	QrfeGlobal::Result readFromTag ( QByteArray tagId, uchar mem_bank, ushort address, QByteArray passwd, uchar count, QByteArray &data );
	QrfeGlobal::Result readMultipleFromTag ( QByteArray epc, QList<uchar> mem_bank, QList<ushort> address, QList<QByteArray> passwd, QList<uchar> count, QList<QByteArray> &data );
	QrfeGlobal::Result writeToTag ( QByteArray tagId, uchar mem_bank, ushort address, QByteArray passwd, QByteArray data );

	QrfeGlobal::Result lockTag ( QByteArray tagId, uchar mode, uchar memory, QByteArray password );
	QrfeGlobal::Result killTag ( QByteArray tagId, uchar rfu, uchar recom, QByteArray password );

	QrfeGlobal::Result customTagCommand ( uchar commandId, QByteArray data, QByteArray &result );

	QrfeGlobal::Result acknowledgeStatusBit ( uchar number );
	QrfeGlobal::Result executeAnalysisFunction ( uchar commandId, QByteArray data, QByteArray &result );

	QrfeGlobal::Result licensePassThrough ( const QByteArray& data );
	QrfeGlobal::Result licenseStartLicenseProcedure ( );
	QrfeGlobal::Result licenseGetLicenseInfo ( ulong& startId, ulong& startCount, ulong& nextId, ulong& remainingCount );
	QrfeGlobal::Result licenseGetReportInfo ( ulong& reportCount );
	QrfeGlobal::Result licenseGetReportData ( ulong reportIndex,  ulong& readerType, ulong& readerId, ulong& flags );
	QrfeGlobal::Result licenseGetErrorReport ( QList<ulong>& errorCounter );

	QrfeGlobal::Result sendHeartBeat();

	void 	blockInterrupts ( bool block );
	bool	interruptsBlocked ( );

signals:
	void heartBeat ();
	void cyclicInventory (const QrfeGlobal::TagEvent &tagInfo);
	void stateChanged (const int newState);
	void statusRegisterChanged (const qulonglong statusRegister);
	void bootUpFinished (const bool finished);
	void notification (const uchar id, const QByteArray& data);
	void applicationInterrupt (const QByteArray& data);
	void gpioValuesChanged ( const ulong gpioValues );
	void licenseDataReceived (const QByteArray& data);
	void licenseResult ( bool res );

private:
	QrfeGlobal::Result send2Reader(uchar com1, uchar com2);
	QrfeGlobal::Result send2Reader(uchar com1, uchar com2, const QByteArray& payload);
	QrfeGlobal::Result waitForResponse(uchar com1, uchar com2, uint waitTime, const QString& funcName, QByteArray& response);
	QrfeGlobal::Result waitForPendingMessage(uchar id, uint waitTime, const QString& funcName, QByteArray& response);

	QrfeGlobal::Result send2ReaderWithoutResponse(uchar com1, uchar com2, const QString& funcName);
	QrfeGlobal::Result send2ReaderWithoutResponse(uchar com1, uchar com2, const QByteArray& payload, const QString& funcName);
	QrfeGlobal::Result send2ReaderWaitForResponse(uchar com1, uchar com2, uint waitTime, const QString& funcName, QByteArray& response);
	QrfeGlobal::Result send2ReaderWaitForResponse(uchar com1, uchar com2, const QByteArray& payload, uint waitTime, const QString& funcName, QByteArray& response);

public slots:
	virtual void deviceWasRemoved();

protected:
	virtual void computeData 	( const QByteArray& data );
	virtual void computeMessage ( const QByteArray& msg );

private slots:
	void heartBeatISR ( const QByteArray& payload );
	void cyclicInventoryISR ( const QByteArray& payload );
	void stateChangedISR ( const QByteArray& payload );
	void statusRegChangedISR ( const QByteArray& payload );
	void bootUpFinishedISR ( const QByteArray& payload );
	void notificationISR ( const QByteArray& payload );
	void applicationISR ( const QByteArray& payload );
	void operationResultISR ( const QByteArray& payload );
	void gpioValuesChangedISR ( const QByteArray& payload );
	void licensePassThroughISR ( const QByteArray& payload );
	void licenseResultISR ( const QByteArray& payload );

	void _q_emit_heartBeat();
	void _q_emit_cyclicInventory(const QrfeGlobal::TagEvent &tagInfo);
	void _q_emit_stateChanged(const int newState);
	void _q_emit_statusRegisterChanged(const qulonglong statusRegister);
	void _q_emit_bootUpFinished(const bool finished);
	void _q_emit_notification(const uchar id, const QByteArray& data);
	void _q_emit_applicationInterrupt(const QByteArray& data);
	void _q_emit_gpioValuesChanged ( const ulong gpioValues );
	void _q_emit_licenseDataReceived(const QByteArray& data);
	void _q_emit_licenseResult ( bool res );

private:
	QrfeGlobal::TagEvent parseTagEvent(const QByteArray& payload, bool& ok);
	int  messageId ( uchar command1, uchar command2 );
	void parserError ( eMessageState state, QByteArray msg, uchar command1, uchar command2 );
	QString state2String( eMessageState state );

private:
	eRFE_RET_VALUE			m_lastReturnCode;

	bool					m_interruptsBlocked;

	QMutex					m_mutex;

	QrfeMessageQueue		m_pendingResultsQueue;
	uint 					m_MAX_PENDING_WAIT_TIME_IN_MS;

private:
	QByteArray 				m_singleMsg;
	eMessageState 			m_state;
	uchar 					m_command1;
	uchar 					m_command2;
	uchar 					m_payloadIndex;
	uchar 					m_payloadLength;

	QByteArray 				m_lastSentMessage;
	QMutex					m_sentMessageMutex;
	QMap<int,QByteArray> 	m_sentMessage;

private:
	bool 					m_useDeprecatedRfFunctions;
};

#endif /* QRFEPROTOCOLLHANDLERRFE_H_ */
