#pragma once

//#include "KsCPP_Exports.h"
#include "..\inc\properties.h"
#include <map>
#include <list>
#include <vector>

class CWizardPage;

class CWizard : public CBCGPDialog
{
	READONLY_PROPERTY(int, start, -1, startId); //setStartId
	READONLY_PROPERTY(int, current, -1, currentId);

public:
	CWizard(UINT nIDTemplate, CWnd* pParentWnd = NULL);

	typedef std::map<int, CWizardPage*> PageMap;
	enum Direction {
		Backward,
		Forward
	};
	enum WizardButton {
		BackButton,
		NextButton,
		CommitButton,
		FinishButton,
		CancelButton,
		HelpButton,
		//CustomButton1,
		//CustomButton2,
		//CustomButton3,
		//Stretch,

		NStandardButtons ,

		NButtons = NStandardButtons,

		NoButton = -1,
		
		
	};

	enum WizardOption {
		NoOptions,
        IndependentPages                = 0x00000001,
        //IgnoreSubTitles                 = 0x00000002,
        //ExtendedWatermarkPixmap         = 0x00000004,
        NoDefaultButton                 = 0x00000008,
        NoBackButtonOnStartPage         = 0x00000010,
        NoBackButtonOnLastPage          = 0x00000020,
        DisabledBackButtonOnLastPage    = 0x00000040,
        HaveNextButtonOnLastPage        = 0x00000080,
        HaveFinishButtonOnEarlyPages    = 0x00000100,
        NoCancelButton                  = 0x00000200,
        //CancelButtonOnLeft              = 0x00000400,
        HaveHelpButton                  = 0x00000800,
        HelpButtonOnRight               = 0x00001000,
        //HaveCustomButton1               = 0x00002000,
        //HaveCustomButton2               = 0x00004000,
        //HaveCustomButton3               = 0x00008000,
        NoCancelButtonOnLastPage        = 0x00010000
    };

	WizardOption opts= CWizard::NoBackButtonOnStartPage;

	int addPage(CWizardPage* page);
	void setPage(int id, CWizardPage* page);
	void removePage(int id);
	CWizardPage* page(int id) const {
		auto it = pageMap.find(id);
		if (it == pageMap.end()) return nullptr;
		else return it->second;
	}
	bool hasVisitedPage(int id) const {
		auto it = std::find(history.begin(), history.end(), id);
		return it != history.end();
	}


	std::vector<int> visitedIds() const {
		return history;
	}
	std::list<int> pageIds() const;
	CWizardPage* currentPage() const {
		return page(current);
	}

	void setStartId(int theid);

	virtual bool validateCurrentPage();
	virtual int nextId() const;

	void setButtonText(WizardButton which, const CString& text);
	//CString buttonText(WizardButton which) const;
	void _q_updateButtonStates();
	void updateButtonTexts();
	void updateButtonLayout();

	void back();
	void next();
	void restart();

	virtual void initializePage(int id);
	virtual void cleanupPage(int id);

	/*!
	This virtual function is called by QWizard::validateCurrentPage()
	when the user clicks \uicontrol Next or \uicontrol Finish to perform some
	last-minute validation. If it returns \c true, the next page is shown
	(or the wizard finishes); otherwise, the current page stays up.

	The default implementation returns \c true.

	When possible, it is usually better style to disable the \uicontrol
	Next or \uicontrol Finish button (by specifying \l{mandatory fields} or
	reimplementing isComplete()) than to reimplement validatePage().

	\sa QWizard::validateCurrentPage(), isComplete()
*/
	virtual bool validatePage()
	{
		return true;
	}
protected:
	PageMap pageMap;
	std::vector<int> history;
	bool startSetByUser = false;
	bool canContinue = false;
	bool canFinish = false;
	std::map<int, CString> buttonCustomTexts;

	CFont fontTitle;
	CFont fontDescription;

	CBCGPStatic labelTitle;
	CBCGPStatic labelDesc;

	// 窗口、控件大小/位置，本类默认一套数值
	// 子类构造时可以修改，子类OnInitDialog或OnSize里应用，不支持动态修改
	int wWidht = 1280;
	int wHeight = 960;

	// 字体大小设置
	int fontSize_title = 240;
	int fontSize_desc = 180;

	// 控件高度设置
	int titleHeight = 32;
	int descHeight = 64;
	int titleLeft = 32;
	int descLeft = 48;
	int titleTop = 16; // title顶部到窗口的距离
	int descTop = 8; // 描述顶部到title底部的距离
	int descBottom = 16; //描述底部空白

	int btnWidth = 100;
	int btnHeight = 48;
	int btnTop = 16; // 按钮顶部空白
	int btnBottom = 16; // 按钮底部空白
	int btnRight = 64; // 按钮右侧空白
	int btnSpace = 16; // 按钮间隔

	// 标题和描述占用的高度，在OnSize()用上面的参数计算
	int headH;
	// 按钮占用的高度，在OnSize()用上面的参数计算
	int footH;


	CBCGPButton btns[CWizard::NButtons];
	void init() {

	}
	void reset();
	void cleanupPagesNotInHistory();
	void switchToPage(int newId, Direction direction);
	void updateCurrentPage();

	void onChangeTitle();
	void onChangeDesc();
	friend class CWizardPage;

	virtual BOOL OnInitDialog();

	afx_msg void OnSize(UINT nType, int cx, int cy);
};

