/**
** This file is owned by VisualGear Technology Co., Ltd.
** Unauthorized copying of this file, via any medium is strictly prohibited
** Otherwise VisualGear Technology Co., Ltd. will have the right to pursue
** maximum responsibilities within scope of legal.
**
** Copyright 2018-2025 VisualGear All rights reserved.
**/


#pragma once

#include <QtWidgets/QLabel>
#include "UIGQMacro.h"
#include "UIGQWidgetBase.h"
#include "UIGQScrollBar.h"
#include "UIGQWindow.h"


#define	UIG_CANVAS_ADD			0x1000
#define UIG_CANVAS_REMOVE		0x1001
#define UIG_CANVAS_SELECT		0x1002
#define UIG_CANVAS_CLEARSELECT	0x1003	
#define UIG_CANVAS_MOVE			0x1004
#define UIG_CANVAS_MOVEUPDOWN	0x1005
#define UIG_CANVAS_RMOUSEUP		0x1006

namespace UIGQtLib
{
	class UIGQCanvas;

	enum UIG_CAV_MODE
	{
		CANVAS_DOWNMOUSE,
		CANVAS_SELECTION,
		CANVAS_DRAGMOVE,
		CANVAS_MOVECTRL,
		CANVAS_CREATEMODE,
		CANVAS_COPYCTRL,
		CANVAS_LAST_MODE
	};

	enum UIG_CAV_HIT_TEST
	{
		CAV_MOVE = 0,
		CAV_LEFT,
		CAV_RIGHT,
		CAV_TOP,
		CAV_BOTTOM,
		CAV_LEFTTOP,
		CAV_LEFTBOTTOM,
		CAV_RIGTHTOP,
		CAV_RIGHTBOTTOM,
		CAV_LAST_HIT
	};

	class CanvasCommand
	{
	public:
		CanvasCommand(UIGQCanvas* canvas) { _canvas = canvas; }
		virtual void Undo() = 0;
		virtual void Redo() = 0;

		UIGQCanvas* _canvas;
		std::vector<QWidget*> _ctrls;
	};

	class SizePosCommand : public CanvasCommand
	{
	public:
		SizePosCommand(UIGQCanvas* canvas) :
			CanvasCommand(canvas)
		{

		}

		virtual void Undo();
		virtual void Redo();
	};

	class CreateCommand : public CanvasCommand
	{
	public:
		CreateCommand(UIGQCanvas* canvas) :
			CanvasCommand(canvas)
		{

		}

		virtual void Undo();
		virtual void Redo();
	};

	class DeleteCommand : public CanvasCommand
	{
	public:
		DeleteCommand(UIGQCanvas* canvas) :
			CanvasCommand(canvas)
		{

		}

		virtual void Undo();
		virtual void Redo();
	};

	class MoveCommand : public CanvasCommand
	{
	public:
		MoveCommand(UIGQCanvas* canvas) :
			CanvasCommand(canvas)
		{
			_offsetX = 0;
			_offsetY = 0;
			_offsetW = 0;
			_offsetH = 0;
		}
		virtual void Undo();
		virtual void Redo();

		int	_offsetX;
		int _offsetY;
		int	_offsetW;
		int _offsetH;
	};

	class UIGEARSQTLIB_EXPORT UIGQCanvasWindow : public QWidget
	{
	public:
		static ControlInfo getProps();
		static const char* typeName() { return "Window"; }
		static QWidget* createCanvas() {
			return new UIGQCanvasWindow(nullptr);
		}

		UIGQCanvasWindow(QWidget* pParent);

		void setShowBackground(bool show);
		void setTransparent(bool enable);
		void setResizeable(bool enable);
		void setBackgroundImage(const QString& imagePath, const ImageDesc& imageDesc);
		void setBackgroundColor(const FillRes& fillRes);
		void setUseFillColor(bool useFillColor);
		
		void setMinWidth(int minWidth);
		void setMinHeight(int minHeight);
		int getMinWidth();
		int getMinHeight();

		void setWidth(int width);
		void setHeight(int height);
		int getWidth();
		int getHeight();

		void setCanDrag(bool bCanDrag);
		bool getCanGrag();
		void setOnlyDragCaption(bool bOnlyCanCaption);
		bool getOnlyDragCaption();
		void setCaptionHeight(int captionHeight);
		bool getCaptionHeight();
		void setX(int x);
		void setY(int y);
		void hideAllWidges();

		QString pageName();
		void setPageName(const QString& name);

		void toJsonString(QString& content);

		QWidget* HitTestWithChildren(QWidget* pParent, int x, int y);

	protected:
		//void paintEvent(QPaintEvent * evt);

	private:
		bool	_canResize;
		bool	_canDrag;
		int		_resizeBorder;
		bool	_isDragableable;
		bool	_isDraging;
		ImageRes _imageRes;
		FillRes  _fillRes;
		bool	_useFill;
		QPoint	_position;
		bool	_showBackground;
		bool	_cursorChange;
		int		_minWidth;
		int		_minHeight;
		bool	_canOnlyDragCaption;
		int		_captionHeight;
		bool	_dbClickMax;
		bool	_isGrabDirty;
		bool	_transparentWin;
		QString _pageName;

	};

	class UIGQCanvasImpl;
	class UIGEARSQTLIB_EXPORT UIGQCanvas : public QWidget, public IUIGQWidgetBase
	{
		Q_OBJECT

	public:
		UIGQCanvas(QWidget* pParent = nullptr);
		~UIGQCanvas();

		bool OpenJsonFile(const QString& filePath);
		void SetProjectPath(const QString& filePath);
		void UpdateSolutionPages();
		void SetScrollbar(UIGQScrollBar* pScrollBar, bool isHor);
		UIGQCanvasWindow* GetCurWindow();
		void AddSelectedControl(QWidget* pSel);
		void RemoveAllSelected();
		QString UpdatePagePath(const QString& page);
		bool SavePage(const QString& page);
		void SaveStyle(const QString& path);
		bool createControl(const QString& typeName);
		void closeAllWindows();
		QString getCurWindowPath();
		bool removePage(UIGQCanvasWindow* pPage);

		UIG_QT_CTRL_DEF("canvas", UIGQCanvas);

	protected:
		bool OpenWindowPage(const QString& filePath);
		void UpdateScrollBar();
		bool CreatePageFromJson(const QString& filePath);
		bool CheckPageValid(const QString&  filePath);
		void RemoveAllCommand();
		void layoutWindow();

		void dragEnterEvent(QDragEnterEvent* pEvent);
		void dragMoveEvent(QDragMoveEvent* pEvent);
		void dropEvent(QDropEvent* pEvent);

		UIG_CAV_HIT_TEST HitInSelected(int x, int y);
		void paintChild(QPainter& painter, const QPoint& offset, QWidget* pWidget);
		bool IsInSelected(QWidget* pEle);
		bool RemoveSelected(QWidget* pEle);
		void resizeEvent(QResizeEvent* pEvent);
		void DrawSelectionPoint(QPainter& painter, int x, int y, bool isAfterEle);

		void mousePressEvent(QMouseEvent *event);
		void mouseReleaseEvent(QMouseEvent *event);
		void mouseMoveEvent(QMouseEvent *event);

	protected:
		void paintEvent(QPaintEvent * evt);

	Q_SIGNALS:
		void widgetSelected(QWidget*);

	public Q_SLOTS:
		void scrollChanged(int value);

	private:
		unsigned int							_createCount = 1;
		UIGQCanvasWindow*						_curOpenWin = nullptr;
		QPixmap									_curWinPixemmap;

		UIGQCanvasImpl*							_ctrlImpl = nullptr;
		QString									_projectPath;

		std::map<QString, UIGQCanvasWindow*>	_mapWindows;
		std::map<UIGQCanvasWindow*, QPoint>		_scrollRecord;

		UIGQScrollBar*							_horScroll;
		UIGQScrollBar*							_verScroll;

		std::vector<CanvasCommand*>				_commandHistroy;

		std::vector<QRect>						_vecDragOldPos;

		std::vector<QWidget*>					_vecSelection;
		std::vector<QWidget*>					_vecCopyCtrl;

		UIG_CAV_MODE							_mode;
		UIG_CAV_HIT_TEST						_hitPos;

		QPoint									_preDownPoint;
		QPoint									_preMovePoint;

		UIGQT_GET_CONTROLBASE;
	};
}

#ifdef UIGQT_NEW_VERSION

#define	UIG_CANVAS_ADD			0x1000
#define UIG_CANVAS_REMOVE		0x1001
#define UIG_CANVAS_SELECT		0x1002
#define UIG_CANVAS_CLEARSELECT	0x1003	
#define UIG_CANVAS_MOVE			0x1004
#define UIG_CANVAS_MOVEUPDOWN	0x1005
#define UIG_CANVAS_RMOUSEUP		0x1006

namespace UIGQtLib
{
	class UIGQCanvas;

	enum UIG_CAV_MODE
	{
		CANVAS_DOWNMOUSE,
		CANVAS_SELECTION,
		CANVAS_DRAGMOVE,
		CANVAS_MOVECTRL,
		CANVAS_CREATEMODE,
		CANVAS_COPYCTRL,
		CANVAS_LAST_MODE
	};

	enum UIG_CAV_HIT_TEST
	{
		CAV_MOVE = 0,
		CAV_LEFT,
		CAV_RIGHT,
		CAV_TOP,
		CAV_BOTTOM,
		CAV_LEFTTOP,
		CAV_LEFTBOTTOM,
		CAV_RIGTHTOP,
		CAV_RIGHTBOTTOM,
		CAV_LAST_HIT
	};

	class CanvasCommand
	{
	public:
		CanvasCommand(UIGQCanvas* canvas) { _canvas = canvas; }
		virtual void Undo() = 0;
		virtual void Redo() = 0;

		UIGQCanvas* _canvas;
		std::vector<QWidget*> _ctrls;
	};

	class SizePosCommand : public CanvasCommand
	{
	public:
		SizePosCommand(UIGQCanvas* canvas) :
			CanvasCommand(canvas)
		{

		}

		virtual void Undo();
		virtual void Redo();
	};

	class CreateCommand : public CanvasCommand
	{
	public:
		CreateCommand(UIGQCanvas* canvas) :
			CanvasCommand(canvas)
		{

		}

		virtual void Undo();
		virtual void Redo();
	};

	class DeleteCommand : public CanvasCommand
	{
	public:
		DeleteCommand(UIGQCanvas* canvas) :
			CanvasCommand(canvas)
		{

		}

		virtual void Undo();
		virtual void Redo();
	};

	class MoveCommand : public CanvasCommand
	{
	public:
		MoveCommand(UIGQCanvas* canvas) :
			CanvasCommand(canvas)
		{
			_offsetX = 0;
			_offsetY = 0;
			_offsetW = 0;
			_offsetH = 0;
		}
		virtual void Undo();
		virtual void Redo();

		int	_offsetX;
		int _offsetY;
		int	_offsetW;
		int _offsetH;
	};

	class UIGQCanvas : public QWidget, public IUIGQWidgetBase
	{
	public:
		UIGQCanvas(QWidget* pParent = nullptr);
		~UIGQCanvas();

		UIG_QT_CTRL_DEF("canvas", UIGQCanvas);

	protected:
		void paintEvent(QPaintEvent * evt);

	private:
		UIGQCanvasImpl* _ctrlImpl;

		UIGQT_GET_CONTROLBASE;


		bool OpenJsonFile(const QString& filePath);
		bool CloseCurPage();
		bool OpenPreviousPage();
		bool OpenNextPage();
		void CloseAllPage();

		bool SaveCurPage();
		bool SavePage(const QString&  page);
		QString UpdatePagePath(const QString&  page);

		void SetProjectPath(const QString& projPath);
		void ResizeElement(bool bResizeChild);
		bool PtInCanvas(int x, int y);

		void OnMouseMove(int flag, int x, int y);
		void OnLMouseDown(int flag, int x, int y);
		void OnRMouseUp(int x, int y);
		void OnLMouseUp(int flag, int x, int y);
		bool OnKeyDown(int vk, int flag);
		bool OnKeyUp(int vk, int flag);
		void MoveSelected(int hor, int ver);
		void DeleteSelected();
		QString GetCurPagePath();

		void SetSelectedControl(QWidget* ctrl);
		void ClearSelection();

		bool CheckPageValid(const QString& filePath);
		bool CreatePageFromJson(const QString& filePath);
		QWidget* GetCurWindow();
		//bool SaveStyle(const QString& filePath);
		//bool OnSetCursor(unsigned int x, unsigned int y);
		void CloseSolution();
		void MoveSelectedUp();
		void MoveSelectedDown();

		void SetScrollbar(UIGQScrollBar* pScrollBar, bool isHor);
		bool RemovePage(const QString& filePath);

		void Undo();
		void Redo();
		void OnMouseWheel(int delta, int x, int y);
		void OnVScroll(int pos);
		void OnHScroll(int pos);
		void UpdateScrollBar();
		bool StartCreateControl(const char* typeName, int x, int y);
		void SetReadFromProjet(bool readFromProject);
		bool ReloadProjectLanguage(const QString& languageFilePath);

		void SetSameX();
		void SetSameY();
		void SetSameRight();
		void SetSameBottom();
		void SetSameSize();
		void SetSameWidth();
		void SetSameHeight();
		void SetAverageWidth();
		void SetAverageHeight();

	protected:
		void resizeEvent(QResizeEvent* pEvent);

		//void DrawSelectionPoint(QPainter& painter, int x, int y, bool isAfterEle = false);
		void PushNewCommand(CanvasCommand* pCmd);
		void RemoveAllCommand();
		bool OpenWindowPage(const QString& filePath);
		void RemoveAllSelected();
		bool RemoveSelected(QWidget* pEle);
		void CopySelection();
		void CutSelection();
		void PasteSelection();
		void AddSelectedControl(QWidget* pSel);
		bool RemovePage(QWidget* pPage);
		UIG_CAV_HIT_TEST HitInSelected(int x, int y);
		bool IsInSelected(QWidget* pEle);

		void SendUIGMessage(int msgId, QObject* pObj, void* param1, void* param2);

	private:
		UIG_CAV_MODE							_mode;
		UIG_CAV_HIT_TEST						_hitPos;

		QPoint									_preDownPoint;
		QPoint									_preMovePoint;

		QRect*									_background;

		std::string								_createCtrlType;
		UIGQWindow*								_curOpenWin;
		std::map<QString, UIGQWindow*>			_mapWindows;
		std::map<QWidget*, QPoint>				_scrollRecord;
		 
		std::vector<QWidget*>					_vecSelection;
		std::vector<QWidget*>					_vecCopyCtrl;

		std::vector<QRect>						_vecDragOldPos;
		std::map<char, std::string>				_key2ControlType;

		std::vector<CanvasCommand*>				_commandHistroy;
		unsigned int							_commandIndex;
		unsigned int								_createCount;
		bool									_shiftMove;
		UIGQScrollBar*							_horScroll;
		UIGQScrollBar*							_verScroll;

		/*CDelegateObj<UIGearsCanvas, UIGearsCanvas>	_eventDelegate;
		HANDLE									_selectHandleEvent;*/
	};
}

#endif
