using System.Collections.Generic;
using Fort23.Core;
using UnityEngine;
namespace Core.Utility
{
    [System.Serializable]
    /// 
    /// 贝塞尔曲线
    /// 
    public class BesselPath : CObject
    {
        public List controlPoints = new List();
        
        /// 
        /// 全部长度
        /// 
        public float allDis;
        public Vector3 CalculatePoint(float t)
        {
            if (controlPoints.Count < 2)
            {
                Debug.LogError("需要至少2个控制点来计算贝塞尔曲线");
                return Vector3.zero;
            }
            t = Mathf.Clamp01(t);
            // return controlPoints[0] * ((1 - t) * (1 - t) * (1 - t)) +
            //        controlPoints[1] * (3 * t * (1 - t) * (1 - t)) +
            //        controlPoints[2] * (3 * t * t * (1 - t)) +
            // controlPoints[3] * (t * t * t);
            int n = controlPoints.Count - 1; // 阶数
            Vector3 point = Vector3.zero;
            for (int i = 0; i <= n; i++)
            {
                // 计算伯恩斯坦多项式
                float bernstein = Bernstein(n, i, t);
                point += bernstein * controlPoints[i];
            }
            return point;
        }
        // 计算伯恩斯坦多项式
        private float Bernstein(int n, int i, float t)
        {
            return BinomialCoefficient(n, i) * Mathf.Pow(1 - t, n - i) * Mathf.Pow(t, i);
        }
        public void SetLengthAtT(int segments = 50)
        {
            allDis = GetLengthAtT(segments);
        }
        public float GetLengthAtT(float t, int segments = 50)
        {
            if (controlPoints.Count < 2) return 0f;
            t = Mathf.Clamp01(t);
            float length = 0f;
            Vector3 previousPoint = CalculatePoint(0);
            float step = 1.0f / segments;
            for (int i = 1; i <= segments; i++)
            {
                float currentT = i * step;
                if (currentT < t)
                {
                    continue;
                }
                Vector3 currentPoint = CalculatePoint(currentT);
                length += Vector3.Distance(previousPoint, currentPoint);
                previousPoint = currentPoint;
            }
            return length;
        }
        // 计算二项式系数 C(n,i)
        private float BinomialCoefficient(int n, int i)
        {
            return Factorial(n) / (Factorial(i) * Factorial(n - i));
        }
        // 计算阶乘
        private float Factorial(int n)
        {
            if (n <= 1) return 1;
            float result = 1;
            for (int i = 2; i <= n; i++)
            {
                result *= i;
            }
            return result;
        }
        // 获取曲线的切线(数值近似)
        public Vector3 GetTangent(float t)
        {
            const float delta = 0.001f;
            t = Mathf.Clamp01(t);
            // 使用数值微分近似切线
            Vector3 p1 = CalculatePoint(t - delta);
            Vector3 p2 = CalculatePoint(t + delta);
            return (p2 - p1).normalized;
        }
        public override void ActiveObj()
        {
        }
        public override void DormancyObj()
        {
            controlPoints.Clear();
        }
    }
}