#ifndef BASEMODEL_H
#define BASEMODEL_H

#include <stable.h>

#include "enum.h"

namespace jop {

class BaseModel : public QObject {

	Q_OBJECT

	Q_PROPERTY(QString title READ title)
	Q_PROPERTY(QString id READ idString)

public:

	struct Field {
		QString name;
		QMetaType::Type type;
	};

	class Value {

	public:

		Value();
		Value(const QString& v);
		Value(int v);
		Value(const QVariant& v);
		int toInt() const;
		QString toString() const;
		QVariant toQVariant() const;
		QMetaType::Type type() const;
		bool isValid() const;
		bool isEqual(const Value& v) const;

	private:

		QMetaType::Type type_;
		QString stringValue_;
		int intValue_;

	};

	BaseModel();
	QStringList changedFields() const;
	static int count(jop::Table table, const QString &parentId);
	bool load(const QString& id);
	bool loadByField(const QString& parentId, const QString& field, const QString& fieldValue);
	bool reload();
	virtual bool save(bool trackChanges = true);
	virtual bool dispose();

	Table table() const;
	virtual QString primaryKey() const;
	virtual bool primaryKeyIsUuid() const;
	virtual bool trackChanges() const;
	virtual QString displayTitle() const;

	bool isNew() const;

	static QVector<BaseModel::Field> tableFields(Table table);
	static bool hasField(jop::Table table, const QString& name);
	static QStringList tableFieldNames(Table table);
	static QString sqlTableFields(Table table);
	static bool isValidFieldName(Table table, const QString& name);
	static void deleteAll(Table table);

	void loadSqlQuery(const QSqlQuery& query);
	void loadJsonObject(const QJsonObject& jsonObject);
	void patchJsonObject(const QJsonObject& jsonObject);
	QHash<QString, Value> values() const;
	Value value(const QString& name) const;
	bool valueIsSet(const QString& name) const;
	void setValue(const QString& name, const Value& value);
	void setValue(const QString& name, const QVariant& value);
	void setValue(const QString& name, const QString& value);
	void setValue(const QString& name, int value);
	void setValue(const QString& name, const QJsonValue& value, QMetaType::Type type);
	//void setValues(const QHash<QString, Value> values);
	Value id() const;
	QString valuesToString() const;
	void clone(const BaseModel& baseModel);

	static QString tableName(Table t);

protected:

	QHash<QString, bool> changedFields_;
	QHash<QString, Value> values_;
	int isNew_;
	jop::Table table_;

	static QVariant cacheGet(const QString& key);
	static void cacheSet(const QString& key, const QVariant& value);
	static void cacheDelete(const QString& key);
	static QMap<int, QVector<BaseModel::Field>> tableFields_;
	static QHash<QString, QVariant> cache_;


public slots:

	QString title() const;
	QString idString() const;

};

}

#endif // BASEMODEL_H
