#ifndef SH_UI_SYNC_H
#define SH_UI_SYNC_H

#include <QObject>
#include <QStringList>
#include <QSet>
#include <QVariant>
#include <QDateTime>
#include <piqt.h>
#include "SH_version.h"
#include "SH_ui_sync_logic.h"

class SHSUiLoader;


class SHUISync: public QObject
{
	Q_OBJECT
public:
	SHUISync();
	
	void assign(SHSUiLoader * loader, bool need_json = false);

	void reset();
	void resetRoles();
	void restoreSourceState();
	void saveForRole(int index);
	void buildDiffForRoles();
	
	PIByteArray diffForRole(int index) const;
	QByteArray buildFullDiffForRole(int index);
	QByteArray buildTransitionDiff(int index_from, int index_to);
	QByteArray buildDiff(bool from_src = false);

	QByteArray convertFromVersion3(QByteArray data);

	static QByteArray widget2JSON(SHSUiLoader * loader);

	enum {
		Version3 = 3,
		CurrentVersion = SHS_UISYNC_VERSION
	};

	QByteArray json_ui, json_diff;

protected:

	struct RoleProperties {
		UiSync::ObjectPropertiesMap src_props;
		UiSync::ObjectPropertiesMap cur_props;
		UiSync::ObjectPropertiesMap override_props;
		UiSync::ObjectPropertiesMap diff;
		PIByteArray serialized_diff;
	};

	void timerEvent(QTimerEvent * );
	void setObjectList(const QObjectList & ol);
	void applyObjectProperties(QObject * o, const UiSync::ObjectProperties & income);
	void applyObjectListProperties(const UiSync::ObjectPropertiesMap & income);
	void parseSignature(QString sig, QString * fname, QString * arg);
	void connectObjectList();
	void signalReveived(QVariant v = QVariant());
	void sendSignal(QWidget * w, const QString & signal_name, const QVariant & v);
	
	QMap<QString, QStringList> signal_names;
	QMap<QString, QString> signal_map;
	QObjectList child_list;
	QSet<QString> slider_classes;
	QHash<QWidget * , QHash<QString, QVariant> > signals_queue;
	QMap<QString, QMap<uint, QString> > prop_hash, signal_by_hash;
	QMap<uint, QObject *> object_by_hash;
	QVector<RoleProperties> properties_by_role;
	UiSync::ObjectPropertiesMap src_props, cur_props;
	UiSync logic;
	bool applying;
	int timer;
	
private slots:
	void signalVoid() {signalReveived();}
	void signalBool(bool v) {signalReveived(QVariant(v));}
	void signalInt(int v) {signalReveived(QVariant(v));}
	void signalDouble(double v) {signalReveived(QVariant(v));}
	void signalQString(QString v) {signalReveived(QVariant(v));}
	void signalQTime(QTime v) {signalReveived(QVariant(v));}
	void signalQDate(QDate v) {signalReveived(QVariant(v));}
	void signalQDateTime(QDateTime v) {signalReveived(QVariant(v));}
	
public slots:
	void applyDiff(QByteArray data);
	void receiveObjectEvent(QByteArray data);
	
signals:
	void objectEvent(QByteArray);
	
};

#endif // SH_UI_SYNC_H
