#pragma once

#include <QList>
#include <vector>
#include <memory>
#include <QMetaType>

namespace Json {

	class Value;

}
class ExplainTreeModelItem;
typedef std::shared_ptr<ExplainTreeModelItem> ExplainTreeModelItemPtr;

/* Columns for tree
 * 0. explain text
 * 1. exclusive times
 * 2. inclusive
 * 3. rows x
 * 4. rows
 * 5. loops
 */

/** \brief Class for the nodes in the QueryExplainModel
 */
class ExplainTreeModelItem: public std::enable_shared_from_this<ExplainTreeModelItem> {
public:
	typedef std::shared_ptr<ExplainTreeModelItem> ItemPtr;

	struct Buffer {
		int hit = 0;
		int read = 0;
		int dirtied = 0;
		int written = 0;

		QString asString() const
		{
			return QString::asprintf("h %d/r %d/d %d/w %d", hit, read, dirtied, written);
		}
	};

	struct TempBlocks {
		int read = 0;
		int written = 0;
	};

	struct IoTimes {
		double read = 0.0;
		double write =0.0;
	};

	ExplainTreeModelItem();
	~ExplainTreeModelItem();

	ExplainTreeModelItem(const ExplainTreeModelItem &rhs) = delete;
	ExplainTreeModelItem &operator=(const ExplainTreeModelItem &rhs) = delete;

	void appendChild(const ItemPtr &child);

	ExplainTreeModelItemPtr child(int row);
	int childCount() const;
	int row() const;
	void setParent(const ItemPtr &parent);
	ItemPtr parent();


	/** ActualTotalTime minus the actual total time of it's children */
	float exclusiveTime() const;
	float inclusiveTime() const;
	float estimateError() const;
	QString detailString() const;

	std::vector<ItemPtr> m_childItems;
	std::weak_ptr<ExplainTreeModelItem> m_parentItem;

	QString nodeType;
	bool    parallelAware = false; // 9.6
	QString strategy;
	QString joinType;
	float   startupCost = 0.f;
	float   totalCost = 0.f;
	int64_t estimatedRows = 0;
	int     planWidth = 0;
	float   actualStartupTime = 0.f;
	float   actualTotalTime = 0.f;
	int64_t actualRows = 0;
	int     actualLoops = 0;

	QString relationName;
	QString alias;
	QString scanDirection;
	QString indexName;
	QString indexCondition;
	QString indexRecheck;
	QString filter;
	QString hashCondition;
	QString sortKey;
	QString sortMethod;
	int sortSpaceUsed = -1;
	QString sortSpaceType;

	// Buffering related
	Buffer sharedBlocks;
	Buffer localBlocks;
	TempBlocks tempBlocks;
	IoTimes ioTimes;

};

class ExplainRoot {
public:
	using SPtr = std::shared_ptr<ExplainRoot>;
	static SPtr createFromJson(Json::Value &json);

	ExplainTreeModelItemPtr plan;
	float planningTime = 0.f;
	// Triggers???
	float executionTime = 0.f;
	float totalRuntime = 0.f;

};

Q_DECLARE_METATYPE(ExplainRoot::SPtr);
