#pragma once
#include <QOpenGLFunctions_4_5_Core>
#include <QVector3D>
#include <vector>

// 颜色常量定义
const float PLANE_COLOR_R = 0.839f;
const float PLANE_COLOR_G = 0.859f;
const float PLANE_COLOR_B = 0.859f;
const float GRID_COLOR_R = 0.102f;
const float GRID_COLOR_G = 0.984f;
const float GRID_COLOR_B = 0.984f;
const float GRID_OFFSET = 0.001f; // 统一网格线偏移量

struct PlanePara
{
	QVector3D origin;
	QVector3D normal;
	QVector3D localX;
	QVector3D localY;
	float halfLength;
	unsigned int gridCntPerEdge;//网格线数量
	float offset;
};

// 继承 QOpenGLFunctions_3_3_Core 以绑定 OpenGL 函数
class WorkPlane : public QOpenGLFunctions_4_5_Core
{
public:
	WorkPlane()
		: m_planeVAO(0), m_planeVBO(0), m_planeEBO(0)
		, m_planeIndexCount(0)
		, m_gridVAO(0), m_gridVBO(0)
		, m_gridVertexCount(0)
	{}

	~WorkPlane()
	{
		// 释放 OpenGL 资源
		glDeleteVertexArrays(1, &m_planeVAO);
		glDeleteBuffers(1, &m_planeVBO);
		glDeleteBuffers(1, &m_planeEBO);
		glDeleteVertexArrays(1, &m_gridVAO);
		glDeleteBuffers(1, &m_gridVBO);
	}

	void initPlane(const PlanePara& para)
	{
		// 初始化 OpenGL 函数（必须调用，绑定上下文）
		initializeOpenGLFunctions();

		// 复制传入参数到成员变量，并修改默认值
		m_para = para;
		//m_para.halfLength = 5.0f;    // 覆盖默认半长
		//m_para.gridCntPerEdge = 12;  // 覆盖默认网格密度
		//m_para.offset = 0.0f;        // 覆盖默认偏移

		// 生成局部坐标系（修改成员变量 m_para 的 localX 和 localY）
		getLocalXY(m_para.normal, m_para.localX, m_para.localY);

		// 绘制平面和网格线（使用成员变量 m_para）
		generatePlaneBase(m_para);
		generateGridLines(m_para);
	}

	void drawPlane()
	{
		// 绘制平面基底
		glBindVertexArray(m_planeVAO);
		glDrawElements(GL_TRIANGLES, m_planeIndexCount, GL_UNSIGNED_INT, 0);

		// 绘制网格线
		glBindVertexArray(m_gridVAO);
		glDrawArrays(GL_LINES, 0, m_gridVertexCount);

		// 解绑 VAO，避免后续操作污染
		glBindVertexArray(0);
	}

private:
	void getLocalXY(const QVector3D& normal, QVector3D& localX, QVector3D& localY)
	{
		QVector3D ref = (qAbs(normal.y()) < 0.999f) ? QVector3D(0, 1, 0) : QVector3D(1, 0, 0);
		localX = QVector3D::crossProduct(normal, ref).normalized();
		localY = QVector3D::crossProduct(normal, localX).normalized();
	}

	void generatePlaneBase(const PlanePara& para)
	{
		//计算出平面四个顶点
		QVector3D pts[4];
		pts[0] = para.origin + (para.halfLength * -para.localX) + (para.halfLength * -para.localY) + (para.offset * para.normal);//原点
		pts[1] = para.origin + (para.halfLength * para.localX) + (para.halfLength * -para.localY) + (para.offset * para.normal);
		pts[2] = para.origin + (para.halfLength * para.localX) + (para.halfLength * para.localY) + (para.offset * para.normal);
		pts[3] = para.origin + (para.halfLength * -para.localX) + (para.halfLength * para.localY) + (para.offset * para.normal);

		// 平面顶点数据（使用常量颜色）
		std::vector<float> vertices = {
			pts[0].x(), pts[0].y(), pts[0].z(), PLANE_COLOR_R, PLANE_COLOR_G, PLANE_COLOR_B,
			pts[1].x(), pts[1].y(), pts[1].z(), PLANE_COLOR_R, PLANE_COLOR_G, PLANE_COLOR_B,
			pts[2].x(), pts[2].y(), pts[2].z(), PLANE_COLOR_R, PLANE_COLOR_G, PLANE_COLOR_B,
			pts[3].x(), pts[3].y(), pts[3].z(), PLANE_COLOR_R, PLANE_COLOR_G, PLANE_COLOR_B
		};

		unsigned int indices[] = { 0, 1, 2, 0, 2, 3 };
		m_planeIndexCount = sizeof(indices) / sizeof(unsigned int); // 避免硬编码 6

		// 生成并配置 VAO/VBO/EBO
		glGenVertexArrays(1, &m_planeVAO);
		glGenBuffers(1, &m_planeVBO);
		glGenBuffers(1, &m_planeEBO);

		glBindVertexArray(m_planeVAO);
		glBindBuffer(GL_ARRAY_BUFFER, m_planeVBO);
		glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(float), vertices.data(), GL_STATIC_DRAW);

		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_planeEBO);
		glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

		// 配置顶点位置属性
		glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0);
		glEnableVertexAttribArray(0);
		// 配置顶点颜色属性
		glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3 * sizeof(float)));
		glEnableVertexAttribArray(1);

		glBindVertexArray(0);//取消绑定（生成的vao一定不为0）
	}

	void generateGridLines(const PlanePara& para)
	{
		std::vector<float> gridVertices;//网格线顶点数组
		float step = 2.0f * para.halfLength / para.gridCntPerEdge;//计算网格线之间的间隔步长(step=平面宽度/网格数量)

		// X方向网格线（平行于localX）
		for (int i = 1; i < para.gridCntPerEdge; ++i)
		{
			float yPos = -para.halfLength + i * step;
			
			//网格线两端位置start/end（平行于localX）
			QVector3D start = para.origin - para.halfLength * para.localX + yPos * para.localY;
			QVector3D end = para.origin + para.halfLength * para.localX + yPos * para.localY;

			//累计偏移量
			start += para.offset * para.normal; // 统一偏移
			end += para.offset * para.normal;

			//顶点数组中插入两组顶点数据
			gridVertices.insert(gridVertices.end(), 
			{
				start.x(), start.y(), start.z(), GRID_COLOR_R, GRID_COLOR_G, GRID_COLOR_B,
				end.x(),   end.y(),   end.z(),   GRID_COLOR_R, GRID_COLOR_G, GRID_COLOR_B
			});
		}

		// Y方向网格线（平行于localY）
		for (int i = 1; i < para.gridCntPerEdge; ++i) 
		{
			float xPos = -para.halfLength + i * step;

			QVector3D start = para.origin - para.halfLength * para.localY + xPos * para.localX;
			QVector3D end = para.origin + para.halfLength * para.localY + xPos * para.localX;

			start += para.offset * para.normal; // 统一偏移
			end += para.offset * para.normal;

			gridVertices.insert(gridVertices.end(), //顶点数组中插入两组顶点数据
			{
				start.x(), start.y(), start.z(), GRID_COLOR_R, GRID_COLOR_G, GRID_COLOR_B,
				end.x(),   end.y(),   end.z(),   GRID_COLOR_R, GRID_COLOR_G, GRID_COLOR_B
			});
		}

		m_gridVertexCount = gridVertices.size() / 6;

		// 生成并配置 VAO/VBO
		glGenVertexArrays(1, &m_gridVAO);
		glGenBuffers(1, &m_gridVBO);

		glBindVertexArray(m_gridVAO);
		glBindBuffer(GL_ARRAY_BUFFER, m_gridVBO);
		glBufferData(GL_ARRAY_BUFFER, gridVertices.size() * sizeof(float), gridVertices.data(), GL_STATIC_DRAW);

		// 配置顶点位置属性
		glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0);
		glEnableVertexAttribArray(0);
		// 配置顶点颜色属性
		glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3 * sizeof(float)));
		glEnableVertexAttribArray(1);

		glBindVertexArray(0);
	}

private:
	PlanePara m_para;
	unsigned int m_planeVAO, m_planeVBO, m_planeEBO;
	int m_planeIndexCount;
	unsigned int m_gridVAO, m_gridVBO;
	int m_gridVertexCount;
};