using SharpDX;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Media.Media3D;

namespace SparkClient.Views.UserControl.ViewportData.Helper
{
    internal class LineCalculationHelper
    {
        private float Y = -0.01F;
        private Vector3 point1;
        private Vector3 center;
        /// <summary>
        /// 常数a(y=ax+b)
        /// </summary>
        private float a;
        /// <summary>
        /// 常数b(y=ax+b)
        /// </summary>
        private float b;
        public LineCalculationHelper(Vector3 point1, Vector3 center) { 
            this.point1 = point1;
            this.center = center;
            this.Y = center.Y;
            this.a = calA(point1, center);
            this.b = calB(point1, a);
        }
        /// <summary>
        /// 常数a的计算
        /// </summary>
        /// <param name="point1"></param>
        /// <param name="center"></param>
        /// <returns></returns>
        private float calA(Vector3 point1, Vector3 center)
        {
            return (point1.Z - center.Z) / (point1.X - center.X);
        }
        /// <summary>
        /// 常数b的计算
        /// </summary>
        /// <param name="point1"></param>
        /// <param name="a"></param>
        /// <returns></returns>
        private float calB(Vector3 point1, float a)
        {
            return -(a * point1.X)+point1.Z;
        }

        public Tuple<Vector3, Vector3> calXline(float length)
        {
            var twoPoint = CalculatePointsOnLine(this.a,length);
            var x1 = twoPoint.p1.X;
            var z1 = twoPoint.p1.Y;
            var x2 = twoPoint.p2.X;
            var z2 = twoPoint.p2.Y;
            return new Tuple<Vector3, Vector3>(new Vector3(x1, Y, z1), new Vector3(x2, Y, z2));
        }
        public Tuple<Vector3, Vector3> calYline(float length)
        {
            var twoPoint = CalculatePointsOnLine(-(1/a), length);
            var x1 = twoPoint.p1.X;
            var z1 = twoPoint.p1.Y;
            var x2 = twoPoint.p2.X;
            var z2 = twoPoint.p2.Y;
            return new Tuple<Vector3, Vector3>(new Vector3(x1, Y, z1), new Vector3(x2, Y, z2));
        }

        public Tuple<Vector3, Vector3> calLineOfOffset(Tuple<Vector3, Vector3> tuple, float d)
        {
            var point1 = tuple.Item1;
            var point2 = tuple.Item2;
            var x1 = point1.X - d * (point2.Z - point1.Z)/
            (float)Math.Sqrt(Square(point2.X - point1.X) + Square(point2.Z - point1.Z));
            var z1 = point1.Z + d * (point2.X - point1.X) /
            (float)Math.Sqrt(Square(point2.X - point1.X) + Square(point2.Z - point1.Z));

            var x2 = point2.X - d * (point2.Z - point1.Z) /
            (float)Math.Sqrt(Square(point2.X - point1.X) + Square(point2.Z - point1.Z));
            var z2 = point2.Z + d * (point2.X - point1.X) /
           (float)Math.Sqrt(Square(point2.X - point1.X) + Square(point2.Z - point1.Z));
            return new Tuple<Vector3, Vector3>(new Vector3(x1, Y, z1), new Vector3(x2, Y, z2));
        }

        float Square(float number)
        {
            return number * number;
        }

        public float calZ(float x, float offset = 0)
        {
            return a * x + b + offset;
        }

        public float calZVertical(float x, float offset = 0)
        {
            return (-x / a)  + b + offset;
        }

        private ((float X, float Y) p1, (float X, float Y) p2) CalculatePointsOnLine(float k ,float L)
        {
            float x0 = center.X;
            float y0 = center.Z;
            // 将距离公式展开并整理为关于 t 的二次方程
            float A = 1 + k * k;
            float B = -2 * x0 + 2 * k * (b - y0);
            float C = x0 * x0 + (b - y0) * (b - y0) - L * L;

            // 计算判别式
            float discriminant = B * B - 4 * A * C;

            if (discriminant < 0)
            {
                throw new InvalidOperationException("无解:距离 L 太小,无法找到满足条件的点。");
            }

            // 计算 t 的两个解
            float t1 = (float)(-B + Math.Sqrt(discriminant)) / (2 * A);
            float t2 = (float)(-B - Math.Sqrt(discriminant)) / (2 * A);

            // 计算两点坐标
            var p1 = (X: t1, Y: (k * t1) + b);
            var p2 = (X: t2, Y: (k * t2) + b);

            return (p1, p2);
        }
    }
}