#ifndef SCRIPT_CONNECTION_H
#define SCRIPT_CONNECTION_H

#include <QObject>
#include <QThread>
#include <QQueue>
#include <QMutex>
#include <QHash>
#include <piblockingqueue.h>
#include "qpiconnection.h"
#include "SH_plugins.h"
#include "SH_runtime.h"

class SHSScriptEngine;
typedef QPair<QList<PIIODevice * >, QByteArray> SHSScriptConnectionInputData;

class SHSScriptConnection: public QObject {
	Q_OBJECT
	friend class SHSScriptEngine;
public:
	explicit SHSScriptConnection(QObject * parent = 0);
	~SHSScriptConnection();
	
	void assignConnection(QPIConnection * conn);
	void sendCommand(int id, const QVector<QVariant> & args);
	void sendToDevice(PIIODevice * dev, const QByteArray & data);
	void sendToAll(const QByteArray & data);
	void prepareConnection();
	void setInactive(bool yes);
	void setLogAddTime(bool yes) {log_add_time = yes;}
	void setLogAddDevice(bool yes) {log_add_dev = yes;}
	void setLogIO(bool yes) {log_io = yes;}
	void start();
	void stop();

private:
	struct DeviceSendStream {
		void init(QPIConnection * conn, PIIODevice * dev, const SHS::DeviceParameters & params);
		void destroy();
		void start();
		void stop();
		PIBlockingQueue<PIByteArray> * send_queue = nullptr;
		PITimer * send_timer = nullptr;
	};
	struct DeviceReadStream {
		int min_size = 1;
		int max_size = 4096;
		PIByteArray stream;
		QByteArray qba;
		PISystemTime last_rec;
	};

	void parseInputData(QList<PIIODevice * > devs, QByteArray data);
	bool tryReceive(SHS::Command & cmd, QByteArray data);
	void initSerials(const PIStringList & devs);
	QString logPrefix(const char * type, const PIIODevice * dev) const;
	void logIO(const char * type, const PIIODevice * dev, const QString & s, const QByteArray & d);
	
	QPIConnection * conn_;
	PIMap<const PIIODevice * , DeviceSendStream> dev_send_stream;
	PIMap<const PIIODevice * , DeviceReadStream> dev_read_stream;
	QHash<int, int> last_send_packet;
	//QQueue<QPair<QList<PIIODevice * >, QByteArray> > rec_queue;
	QMutex rec_mutex;
	QTime tm;
	int timer;
	bool inactive, log_add_time, log_add_dev, log_io;

private slots:
	void qDataReceived(SHSScriptConnectionInputData data) {parseInputData(data.first, data.second);}
	void connDataReceived(QString dev, QByteArray data);
	void connPacketReceived(QString filter, QByteArray data);
	
signals:
	void received(SHS::Command * cmd, QVariantMap args);
	void logIOEvent(QString msg);
	
};

#endif // SCRIPT_CONNECTION_H
