#pragma once
#include "QxModelView.h"
#include "QxOrm.h"
#include "OrmModelBase.h"

template<typename T>
class QxModelBase : public qx::QxModel<T, OrmModelBase>
{
public :
	QxModelBase(QObject * parent = nullptr) 
		:qx::QxModel<T, OrmModelBase>(parent), 
		isAutoInsert(false){};

	virtual ~QxModelBase(){ ; };

    void setAutoInsert(bool isAutoInsert = true){ this->isAutoInsert = isAutoInsert; }

protected:
	bool isAutoInsert;

public:
	virtual QSqlError qxSaveRowData(int row, const QStringList & column = QStringList(), QSqlDatabase * pDatabase = nullptr)
	{
		if (!this->m_pDataMemberId) { this->m_lastError = QSqlError("[QxOrm] problem with 'qxSaveRowData()' method : 'data member id not registered'", "", QSqlError::UnknownError); return this->m_lastError; }
		type_ptr pItem = getRowItemAt(row); if (!pItem) { return QSqlError(); }
		QVariant id = this->m_pDataMemberId->toVariant(pItem.get());
		bool bExist = qx::trait::is_valid_primary_key(id);
		if (bExist) { bExist = qx::dao::exist((*pItem), this->database(pDatabase)); }
		if (bExist) { this->m_lastError = qx::dao::update((*pItem), this->database(pDatabase), column); }
		else if (isAutoInsert){ this->m_lastError = qx::dao::insert((*pItem), this->database(pDatabase)); }
		return this->m_lastError;
	}

	virtual void insertDirtyRowToModel() 
	{
		qx::QxModel<T, OrmModelBase>::insertDirtyRowToModel();
	}

	void countWithRelation(const qx::QxSqlQuery  &query, const QStringList &relation)
	{
		qx::dao::count_with_relation<T>(totalCount, relation, query);
	}

	virtual QSqlError qxFetchRow(int row, const QStringList & relation, QSqlDatabase * pDatabase)
	{
		using namespace qx;
		type_ptr pItem = getRowItemAt(row); if (!pItem) { return QSqlError(); }
		if (relation.count() == 0)
		{
			this->m_lastError = qx::dao::fetch_by_id((*pItem), this->database(pDatabase), this->m_lstColumns);
		}
		else
		{
			QxSqlQuery query;
			query.where("t." + m_pDataMemberId->getKey()).isEqualTo(m_pDataMemberId->toVariant(pItem.get()));
			QStringList relations;
			relations << "<t>";
			QString placeholder[] = { "b", "c", "d", "e", "f", "g", "h" };
			int i = 0;
			for (auto dataMember : m_lstDataMember)
			{
				if (dataMember->hasSqlRelation())
				{
					relations << dataMember->getKey() + "<" + placeholder[i] + ">";
					i++;
				}
			}
			this->m_lastError = qx::dao::fetch_by_query_with_relation(relations, query, (*pItem), this->database(pDatabase));
		}
		if (this->m_lastError.isValid())
		{
			return this->m_lastError;
		}

		QModelIndex idxTopLeft = this->index(row, 0);
		QModelIndex idxBottomRight = this->index(row, (this->m_lstDataMember.count() - 1));
		this->raiseEvent_dataChanged(idxTopLeft, idxBottomRight);
		updateKey(row);
		return this->m_lastError;
	}

	std::shared_ptr<T> getByRow(int row) const
	{
		return m_model.getByIndex(row);
	}
};
