#pragma once
#include "../../Backend/Globalincludes.h"

#include <unordered_map>


typedef int GuiFlags;
typedef int DrawListType;

namespace GamesenseMenuFramework {

	struct HSV {
		float h;
		float s;
		float v;
		float a;

		HSV() {
			h = 0;
			s = 0;
			v = 0;
			a = 255;
		}

		HSV(float h_, float s_, float v_, float a_) {
			h = h_;
			s = s_;
			v = v_;
			a = a_;
		}
	};

	struct Vec2 {
		float x, y;

		Vec2() { x = y = 0; }
		Vec2(float _x, float _y) { x = _x; y = _y; }
		
		Vec2& operator+=(const Vec2& other)
		{
			x += other.x;
			y += other.y;
			return *this;
		}
		Vec2& operator-=(const Vec2& other)
		{
			x -= other.x;
			y -= other.y;
			return *this;
		}
		Vec2 operator+(const Vec2& other)
		{
			return Vec2(x + other.x, y + other.y);
		}

		Vec2 operator-(const Vec2& other)
		{
			return Vec2(x - other.x, y - other.y);
		}

		bool operator==(const Vec2& other) const {
			return x == other.x && y == other.y;
		}
	};

	struct Rect {
		Vec2 Min;
		Vec2 Max;

		Rect() : Min(FLT_MAX, FLT_MAX), Max(-FLT_MAX, -FLT_MAX) {}
		Rect(const Vec2& min, const Vec2& max) : Min(min), Max(max) {}
		Rect(float x1, float y1, float x2, float y2) : Min(x1, y1), Max(x2, y2) {}
	};

	class DrawList {
	private:
		struct RenderObject {
			DrawListType Type;
			Vec2		 Pos;
			Vec2		 Size;
			RLColor		 Color;
			RLColor		 OtherColor;
			const char*  Text;
			RLFont	     Font;
			bool		 Bordered;
			bool		 Vertical;
			Vec2		 TextClipSize;
			bool		 Antialias;

			RenderObject(DrawListType Type, Vec2 Pos, Vec2 Size, RLColor color, RLColor OtherColor, const char* text, RLFont font, bool Bordered, bool Vertical, Vec2 TextClipSize, bool Antialias) {
				this->Type = Type;
				this->Pos = Pos;
				this->Size = Size;
				this->Color = color;
				this->OtherColor = OtherColor;
				this->Text = text;
				this->Font = font;
				this->Bordered = Bordered;
				this->Vertical = Vertical;
				this->TextClipSize = TextClipSize;
				this->Antialias = Antialias;
			}
		};
	public:
		static std::vector<RenderObject> Drawlist;
		static void AddText(const char* text, int x, int y, RLColor Color, RLFont font, bool Bordered = false, Vec2 TextClipSize = Vec2(0, 0));
		static void AddFilledRect(Vec2 Pos, Vec2 Size, RLColor Color);
		static void AddRect(Vec2 Pos, Vec2 Size, RLColor Color, bool Antialias = false);
		static void	AddGradient(Vec2 Pos, Vec2 Size, RLColor Color, RLColor OtherColor, bool Vertical = false, bool Antialias = false);
	};

	enum DrawListType_ {
		DrawType_Text			   = 0,
		DrawType_FilledRect		   = 1,
		DrawType_Rect			   = 2,
		DrawType_Gradient		   = 3,
		DrawType_Triangle		   = 4
	};

	enum GuiFlags_ {
		GuiFlags_None			   = 0,
		GuiFlags_NoMove			   = 1 << 1,
		GuiFlags_NoResize		   = 1 << 2,
		GuiFlags_ReturnKeyReleased = 1 << 3,
		GuiFlags_NoTabButton	   = 1 << 4,
		GuiFlags_ChildWindow	   = 1 << 5,
		GuiFlags_PopUp			   = 1 << 6,
		GuiFlags_TabButton		   = 1 << 7,
		GuiFlags_CheckBox		   = 1 << 8,
		GuiFlags_Button			   = 1 << 9,
		GuiFlags_FloatSlider	   = 1 << 10,
		GuiFlags_IntSlider		   = 1 << 11,
		GuiFlags_ComboBox		   = 1 << 12,
		GuiFlags_Selectable		   = 1 << 13,
		GuiFlags_SingleSelect	   = 1 << 14,
		GuiFlags_ColorPicker	   = 1 << 15,
		GuiFlags_Label             = 1 << 16,
		GuiFlags_LegitTab		   = 1 << 17,
		GuiFlags_Listbox		   = 1 << 18,
		GuiFlags_NoKeyBindMenu	   = 1 << 19,
		GuiFlags_MultiKey		   = 1 << 20
	};

	struct GuiWindow {
		std::string				 Name;
		GuiFlags				 Flags;

		Vec2					 Pos, Size;
		Vec2					 CursorPos;
		Vec2					 PevCursorPos;
		Vec2					 PrevCursorPos;
		
		GuiWindow*				 ParentWindow;
		std::vector<GuiWindow*>  ChildWindows;
		std::vector<GuiWindow*>  PopUpWindows;

		std::string				 SelectedItem;

		bool					 Opened;
		bool					 Dragging;
		bool					 Resizing;
		bool					 Block;
		bool					 Init;
		bool					 WidgetClicked;
		std::unordered_map<const char*, bool> ItemActive;

		int					     xSize = 3;
		int						 ySize = 10;
		int						 xPos = 0;
		int						 yPos = 0;

		float					 ScrollRatio;
	};

	struct NextWindowInfo {
		Vec2					 Pos;
		Vec2					 Size;
		bool					 PosCond;
		bool					 SizeCond;
	};

	struct GuiContext {
		bool					 Initialized;
		std::vector<GuiWindow*>  Windows;
		std::vector<std::string> WindowsByName;
		GuiWindow*				 CurrentWindow;
		NextWindowInfo			 NextWindowInfo;
		Vec2					 ItemSpacing;
		int						 MenuAlpha;
		float					 dpiScale = 1.0f;


		bool					 KeyState[256];
		bool					 PrevKeyState[256];
		Vec2					 MousePos;
		Vec2					 PrevMousePos;
		float					 MouseWheel = 0.f;
		bool					 AwaitingInput = false;
		bool					 IsBindingKey = false;
		int						 LastInput = 0;
	};

	namespace ui {
		//-------Helpers-------//中文
		bool					 IsInside(float x, float y, float w, float h); // 检查鼠标是否在矩形内
		bool					 IsInsideWindow(GuiWindow* Window = 0); // 检查鼠标是否在窗口内
		bool					 KeyPressed(const int key); // 检查按键是否被按下
		bool					 KeyDown(const int key); // 检查按键是否被按下
		bool					 KeyReleased(const int key); // 检查按键是否被释放
		bool					 ButtonBehavior(GuiWindow* Window, const char* label, Rect bb, bool& hovered, bool& held, GuiFlags flags = NULL); // 按钮行为
		bool					 ChildsAreStable(GuiWindow* Window); // 检查子窗口是否稳定
		bool					 PopUpsAreClosed(GuiWindow* Window); // 检查弹出窗口是否关闭关闭
		void					 HandleMoving(GuiWindow* Window, Rect Constraints = Rect{}, Vec2* v = nullptr); // 处理窗口移动
		void					 HandleResize(GuiWindow* Window, Rect Constraints = Rect{}, Vec2* buffer = nullptr); // 处理窗口调整大小
		void					 AddItemToWindow(GuiWindow* Window, Rect size, GuiFlags flags = NULL); // 添加窗口项
		bool					 NoItemsActive(GuiWindow* Window); // 检查窗口项是否激活
		template				 <typename T> // 滑块行为
		bool					 SliderBehavior(const char* item_id, Rect bb, T value, T min_value, T max_value, GuiFlags flags); // 滑块行为
		HSV						 ColorPickerBehavior(GuiWindow* PickerWindow, Rect& RcColor, Rect& RcAlpha, Rect& RcHue, int col[4], bool reset = false); // 颜色选择器行为
		//-------Context-------//
		void					 Shutdown(GuiContext* context); // 关闭上下文
		void					 Init(GuiContext* context); // 初始化上下文
		GuiContext*				 CreateContext(); // 创建上下文
		void					 DeleteContext(GuiContext* ctx); // 删除上下文
		//-------WindoW------//
		GuiWindow*				 FindWindowByName(const char*& name); // 根据名称查找窗口
		static GuiWindow*		 CreateNewWindow(const char*& name, Vec2 size, GuiFlags flags); // 创建新窗口
		void					 GetInputFromWindow(const std::string& window_name); // 获取窗口输入
		GuiWindow*				 GetCurrentWindow(); // 获取当前窗口
		void					 SetCurrentWindow(GuiWindow* window); // 设置当前窗口

		void					 SetWindowSize(GuiWindow* window, const Vec2& size); // 设置窗口大小
		void					 SetWindowSize(const Vec2& size); // 设置窗口大小
		void					 SetWindowSize(const char* name, const Vec2& size); // 设置窗口大小
		Vec2		   			 GetWindowSize(); // 获取窗口大小
		Vec2					 GetWindowPos(); // 获取窗口位置

		void					 SetWindowPos(GuiWindow* window, const Vec2& pos); // 设置窗口位置
		void 					 SetWindowPos(const Vec2& pos); // 设置窗口位置
		void					 SetNextWindowPos(const Vec2& pos); // 设置下一个窗口位置
		void					 SetNextWindowSize(const Vec2& size); // 设置下一个窗口大小

		void					 Begin(const char* Id, GuiFlags flags); // 开始绘制
		void					 End(); // 结束绘制

		void					 BeginChild(const char* id, Rect X = { Vec2(0, 0), Vec2(3,10) }, GuiFlags flags = NULL); // 开始绘制子窗口
		void					 EndChild(); // 结束绘制子窗口

		void					 TabButton(const char* label, int* selected, int num, int total, GuiFlags flags = NULL); // 绘制选项卡按钮
		bool					 Checkbox(const char* label, bool* v, bool special = false, bool* rightClicked = nullptr); // 绘制复选框
		bool					 Button(const char* label, const Vec2& size = Vec2(0, 0)); // 绘制按钮
		void					 SliderInt(const char* label, int* v, int v_min, int v_max, const char* format = NULL, int remove = 0); // 绘制整数滑块
		void					 SliderFloat(const char* label, float* v, float v_min, float v_max, const char* format, float scale); // 绘制浮点数滑块
		bool					 SingleSelect(const char* label, int* current_item, std::vector<const char*> items); // 绘制单选框
	
		bool					 MultiSelect(const char* label, std::unordered_map<int, bool>* data, std::vector<const char*> items); // 绘制多选框
		bool					 ColorPicker(const char* label, int col[4], GuiFlags flags = NULL); // 绘制颜色选择器
		bool				 	 KeyBind(const char* id, int* current_key, int* key_style, GuiFlags flags = GuiFlags_None); // 单键绑定
		bool					 MultiKeyBind(const char* label, int* keystyle, GuiFlags flags = GuiFlags_None); // 多键组合绑定
		void					 Label(const char* label, bool special = false, GuiFlags flags = NULL); // 绘制标签
		void					 InputText(const char* id, char* buffer, GuiFlags flags = NULL); // 绘制输入文本框
		
		template				 <typename T> // 绘制滑块
		void					 Slider(const char* label, T* v, T v_min, T v_max, const char* format = NULL, GuiFlags flags = NULL, float scale = 1.f, int remove = 0.f); // 绘制滑块
		bool					 ComboSelectable(const char* label, bool selected = false, GuiFlags flags = NULL, const Vec2& size_arg = Vec2(0, 0)); // 绘制下拉选择框
		bool					 Selectable(const char* label, bool activated, const Vec2& size_arg = Vec2()); // 绘制可选框
		
		bool					 BeginCombo(const char* label, const char* preview_value, int items, GuiFlags flags = NULL); // 开始绘制下拉选择框
		void					 EndCombo(); // 结束绘制下拉选择框
		bool					 BeginListbox(const char* id, const Vec2 Size = Vec2(), GuiFlags flags = NULL); // 开始绘制列表框
		void					 EndListbox(); // 结束绘制列表框
	}

	namespace Globals {
		extern GuiContext*	     Gui_Ctx;
		// Multi-key bind cache: returns ref to persistent string for cfgKey
		std::string& MultiKeyCache(const std::string& cfgKey);
	}

}