#ifndef _PvTable_H_
#define _PvTable_H_

#include <functional>

#include "PvApp.h"
#include "Fields.h"

using CallbackTableOpt = std::function<void(int row, int col, std::string text)>;

class PvTable : public PvObject
{
public:
	struct Options
	{
		bool show_header = true;
		bool show_border = true;
		int head_height = 40;
		int row_height = 35;
	};

	struct Head
	{
		Head() {}
		Head(std::string hid, std::string htext, int w, std::vector<std::pair<std::string, std::string>> mapping) 
			: id(hid), text(htext), width(w), vecMaping(mapping) {}

		std::string id;
		std::string text;
		int width = 80;
		int pvid = PV_ID_NUL;
		vector<pair<string, string>> vecMaping;

		std::string getMapping(std::string s)
		{
			std::string v = s;
			for (auto& item : vecMaping)
			{
				if (v == item.first) { v = item.second; }
				else if (v == item.second) { v = item.first; }
			}
			return v;
		}
	};

	struct Row
	{
		bool visible = false;
		int widget {PV_ID_NUL};
		std::vector<int> vecCells {};
	};

public:
	PvTable(PARAM* p, int parent, int x, int y, int w, int rowCount, Options& option);

	void addHead(std::string id, std::string text, int width, std::vector<std::pair<std::string, std::string>> mapping = {});
	void addHead(std::vector<std::string> vecText);

	void setRowVisible(int irow, bool v);
	void highlight(int irow, bool v);

	void addOperate(std::vector<std::string> vecOpt);
	void setOperateCallback(CallbackTableOpt cb);


	void setRow(int irow, Fields& d);
	void setRow(int irow, std::vector<std::string> vd);
	Fields row(int irow);
	Fields rowMapping(int irow);

	void mappingData(Fields& fields);

	int rowCount();
	int colCount();

	std::vector<Fields> data();

	PvTable::Head& header(int col);

private:
	Options option;
	PvRect rect;

	std::vector<PvTable::Head> vecHeads;
	std::vector<PvTable::Row> vecRows;
	std::vector<Fields> vecData;

	vector<pair<int, vector<int>>> vecOper;
	int nrow;
	int ncol;

	int posCol = 0;
	
	CallbackTableOpt callbackOper = nullptr;
};


class PvPagination : public PvObject
{
public:
	PvPagination(PARAM* p, int parent, int x, int y, int n);

	void setPage(int index, int count);

	int page();

	void setCallback(std::function<void(int index)> func);

private:
	void activePage(int index, bool invoke=false);

private:
	// 当前显示的页码索引, 从1开始
	int pageIndex = 1;

	// 总页数
	int pageCount = 0;

	// 上一页按钮
	int btnPrev = PV_ID_NUL;

	// 下一页按钮
	int btnNext = PV_ID_NUL;

	int btnActive = PV_ID_NUL;

	int labelInfo = PV_ID_NUL;

	// 页码列表（最多显示6个页码按钮,前3页和后3页） <按钮ID, 页码>
	std::vector<pair<int, int>> vecBtn;

	function<void(int)> callback = nullptr;
};


///////////////////////////////////////////////////////////////////////////////////////////////////
// === PageTable ===
class PvPopWidget;
class PageTable : public PvMask
{
public:
	PageTable(PARAM* p);

	void setPage(int pageIndex, int pageSize, int count) {}

	std::shared_ptr<PvPopWidget> addPop(int w, int h, int w0, std::string name, std::vector<std::string> primaryKeys);

	void showPop(int index, std::string optr, Fields fields);
	void hidePop(int index);

	void updateDataFromDB();

	virtual void onQueryTable(PageInfo& pageInfo, std::vector<Fields>& result) {}
	virtual void onOperate(int row, int col, std::string oper) {};
	virtual std::string onValidation(std::shared_ptr<PvPopWidget> pop, Fields& fields) { return ""; };
	virtual std::string onPopConfirm(std::shared_ptr<PvPopWidget> pop, Fields& fields) { return ""; };

	int pageSize {15};
	int pageIndex {0};
	PvTable::Options option;
	std::shared_ptr<PvTable> table;
	std::shared_ptr<PvPagination> pagination;
	std::vector<std::shared_ptr<PvPopWidget>> vecPop;
	Fields curRowData;
};

#endif // ! _PvTable_H_