using UnityEngine;

namespace MindPowerSdk
{
    public partial class MPMap
    {
        public const float SEA_LEVEL = 0.0f;

        private static readonly int[,] Offset =
        {
            { 0, 0 },
            { 1, 0 },
            { 0, 1 },
            { 1, 1 }
        };

        private MPTile GetGroupTile(int x, int y, int no)
        {
            return GetTile(x + Offset[no, 0], y + Offset[no, 1]);
        }

        /// <summary>
        /// 获取地形的高度
        /// </summary>
        /// <param name="fX"></param>
        /// <param name="fY"></param>
        /// <returns></returns>
        public float GetHeight(float fX, float fY)
        {
            // 将浮点坐标转换为整数坐标(取整)
            int nX = (int)fX;
            int nY = (int)fY;

            // 计算四个角点的坐标(构成一个单位矩形)
            float fx1 = (float)nX;
            float fx2 = (float)nX + 1;
            float fy1 = (float)nY;
            float fy2 = (float)nY + 1;

            // 初始化四个顶点的高度(默认海平面)
            float[] fHeight = new float[4] { SEA_LEVEL, SEA_LEVEL, SEA_LEVEL, SEA_LEVEL };

            // 获取基准瓦片
            MPTile pTile = GetTile(nX, nY);
            // 遍历四个顶点获取实际高度
            for (int i = 0; i < 4; i++)
            {
                MPTile pCurTile = GetGroupTile(nX, nY, i);
                fHeight[i] = pCurTile.Height;
            }

            // 构建四个三维顶点
            Vector3 v0 = new Vector3(fx1, fy1, fHeight[0]);
            Vector3 v1 = new Vector3(fx2, fy1, fHeight[1]);
            Vector3 v2 = new Vector3(fx1, fy2, fHeight[2]);
            Vector3 v3 = new Vector3(fx2, fy2, fHeight[3]);

            // 创建射线(从高处垂直向下)
            Vector3 vOrig = new Vector3(fX, fY, 20.0f); // 起点
            Vector3 vDir = new Vector3(0, 0, -1); // 方向向下
            float u, v; // 用于存储交点参数

            Vector3 vPickPos;
            // 检测与第一个三角形(v0-v1-v2)的相交
            if (IntersectTri(v0, v1, v2, vOrig, vDir, out u, out v))
            {
                vPickPos = v0 + u * (v1 - v0) + v * (v2 - v0);
                return vPickPos.z; // 返回交点的Z值(高度)
            }

            // 检测与第二个三角形(v2-v1-v3)的相交
            if (IntersectTri(v2, v1, v3, vOrig, vDir, out u, out v))
            {
                vPickPos = v2 + u * (v1 - v2) + v * (v3 - v2);
                return vPickPos.z;
            }

            // 无交点返回0
            return 0.0f;
        }

        // Unity版本的三角形射线相交检测
        bool IntersectTri(Vector3 v0, Vector3 v1, Vector3 v2, Vector3 origin, Vector3 direction, out float u, out float v)
        {
            u = v = 0;
            Vector3 edge1 = v1 - v0;
            Vector3 edge2 = v2 - v0;

            // 计算行列式
            Vector3 pvec = Vector3.Cross(direction, edge2);
            float det = Vector3.Dot(edge1, pvec);

            // 背面剔除(det > 0 可改为 det < 0 如果需要双面检测)
            if (det < Mathf.Epsilon)
                return false;

            // 计算U参数并测试范围
            Vector3 tvec = origin - v0;
            u = Vector3.Dot(tvec, pvec);
            if (u < 0 || u > det) return false;

            // 计算V参数并测试范围
            Vector3 qvec = Vector3.Cross(tvec, edge1);
            v = Vector3.Dot(direction, qvec);
            if (v < 0 || u + v > det) return false;

            // 归一化参数
            float invDet = 1.0f / det;
            u *= invDet;
            v *= invDet;

            return true;
        }

        /// <summary>
        /// 返回结束位置与矩形大小
        /// </summary>
        /// <param name="startX"></param>
        /// <param name="startY"></param>
        /// <param name="showSize"></param>
        /// <returns></returns>
        public RectInt GetRect(short startX, short startY, int showSize)
        {
            int endX = Mathf.Min(startX + showSize, Width);
            int endY = Mathf.Min(startY + showSize, Height);

            // 本次宽高
            int width = endX - startX;
            int height = endY - startY;

            return new RectInt(endX, endY, width, height);
        }

        public Mesh GenMesh(short startX, short startY, int showSize)
        {
            RectInt rect = GetRect(startX, startY, showSize);

            // 顶点
            int verticesNum = (rect.width) * (rect.height) * 4;
            Vector3[] vertices = new Vector3[verticesNum];
            int[] triangles = new int[verticesNum * 6];
            Vector2[] uv0 = new Vector2[verticesNum];
            Vector2[] uv2 = new Vector2[verticesNum];
            int vertIdx = 0;
            int triIdx = 0;

            for (short y = startY; y < rect.y; y++)
            {
                for (short x = startX; x < rect.x; x++)
                {
                    // 添加4个顶点
                    for (int i = 0; i < 4; i++)
                    {
                        MPTile tile = GetGroupTile(x, y, i);
                        vertices[vertIdx + i] = new Vector3(x + Offset[i, 0], tile.Height, (y + Offset[i, 1]) * -1);
                        // Debug.Log($"{x},{y}");

                        // uv 整个mesh映射到一张贴图上
                        int rx = x - startX;
                        // int ry = rect.y - y - 2;
                        int ry = y - startY + 1;
                        uv0[vertIdx + i] = new Vector2((rx + Offset[i, 0]) / (float)rect.width, (ry + Offset[i, 1]) * -1 / (float)rect.height);
                        uv2[vertIdx + i] = new Vector2(Offset[i, 0], Offset[i, 1] * -1);
                    }

                    triangles[triIdx + 0] = vertIdx + 2;
                    triangles[triIdx + 1] = vertIdx + 0;
                    triangles[triIdx + 2] = vertIdx + 3;

                    triangles[triIdx + 3] = vertIdx + 0;
                    triangles[triIdx + 4] = vertIdx + 1;
                    triangles[triIdx + 5] = vertIdx + 3;

                    vertIdx += 4;
                    triIdx += 6;
                }
            }

            Mesh mesh = new Mesh();
            mesh.SetVertices(vertices);
            mesh.SetTriangles(triangles, 0);
            mesh.SetUVs(0, uv0);
            mesh.SetUVs(2, uv2);


            return mesh;
        }

        public (Texture2D, Texture2D) GenTxtNoTexture(short startX, short startY, int showSize)
        {
            RectInt rect = GetRect(startX, startY, showSize);

            Texture2D texture1 = new Texture2D(rect.width, rect.height, TextureFormat.RGBA32, false, true); // 贴图值: texNo
            texture1.filterMode = FilterMode.Point;

            Texture2D texture2 = new Texture2D(rect.width, rect.height, TextureFormat.RGBA32, false, true); // 遮罩值:alphaNo
            texture2.filterMode = FilterMode.Point;

            for (short y = startY; y < rect.y; y++)
            {
                for (short x = startX; x < rect.x; x++)
                {
                    MPTile tile = GetTile(x, y);

                    // 4层数据
                    float r = (tile.TexLayer[0].TexNo - 1) / 64f;
                    float g = (tile.TexLayer[1].TexNo - 1) / 64f;
                    float b = (tile.TexLayer[2].TexNo - 1) / 64f;
                    float a = (tile.TexLayer[3].TexNo - 1) / 64f;

                    int rx = x - startX;
                    int ry = rect.y - 1 - y;
                    texture1.SetPixel(rx, ry, new Color(r, g, b, a));

                    var alphaNo = new Color(
                        (tile.TexLayer[0].AlphaNo - 1) / 16f,
                        (tile.TexLayer[1].AlphaNo - 1) / 16f,
                        (tile.TexLayer[2].AlphaNo - 1) / 16f,
                        (tile.TexLayer[3].AlphaNo - 1) / 16f);
                    texture2.SetPixel(rx, ry, alphaNo);

                    if (alphaNo.r > 48 || alphaNo.g > 48 || alphaNo.b > 48 || alphaNo.a > 48)
                    {
                        Debug.LogError($"{rx},{ry}|{alphaNo}");
                    }
                }
            }

            texture1.Apply();
            texture2.Apply();

            return (texture1, texture2);
        }
    }
}