using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;

namespace Ink_Canvas.Helpers
{
    /// <summary>
    /// 硬件加速的墨迹处理器，利用WPF的GPU渲染能力
    /// </summary>
    public class HardwareAcceleratedInkProcessor : IDisposable
    {
        private readonly RenderTargetBitmap _renderTarget;
        private readonly DrawingVisual _drawingVisual;
        private bool _isInitialized;

        public HardwareAcceleratedInkProcessor(int width = 1920, int height = 1080)
        {
            // 创建硬件加速的渲染目标
            _renderTarget = new RenderTargetBitmap(width, height, 96, 96, PixelFormats.Pbgra32);
            _drawingVisual = new DrawingVisual();

            // 启用硬件加速
            RenderOptions.SetBitmapScalingMode(_drawingVisual, BitmapScalingMode.HighQuality);
            RenderOptions.SetEdgeMode(_drawingVisual, EdgeMode.Aliased);

            _isInitialized = true;
        }

        /// <summary>
        /// 使用GPU加速的贝塞尔曲线平滑
        /// </summary>
        /// <summary>
        /// 使用GPU加速的贝塞尔曲线平滑。
        /// 注意：本方法在 UI 线程调用（来自 StrokeCollected 路径），WPF Stroke / StylusPointCollection
        /// 是 DispatcherObject 但不是 Freezable——为安全起见不再用 Task.Run，避免跨线程访问
        /// 触发 "必须在创建线程使用" 异常。仅 DrawingAttributes (Freezable) 被克隆并冻结。
        /// </summary>
        public Task<Stroke> SmoothStrokeWithGPU(Stroke originalStroke)
        {
            if (!_isInitialized || originalStroke == null || originalStroke.StylusPoints.Count < 2)
                return Task.FromResult(originalStroke);

            try
            {
                // 使用PathGeometry进行硬件加速的曲线拟合
                var pathGeometry = CreateSmoothPathGeometry(originalStroke.StylusPoints);

                // 将PathGeometry转换回StylusPoint集合
                var smoothedPoints = ConvertPathGeometryToStylusPoints(pathGeometry, originalStroke.StylusPoints);

                var da = originalStroke.DrawingAttributes.Clone();
                var result = new Stroke(new StylusPointCollection(smoothedPoints))
                {
                    DrawingAttributes = da
                };
                return Task.FromResult(result);
            }
            catch
            {
                return Task.FromResult(originalStroke);
            }
        }

        /// <summary>
        /// 创建平滑的路径几何体
        /// </summary>
        private PathGeometry CreateSmoothPathGeometry(StylusPointCollection points)
        {
            var pathGeometry = new PathGeometry();
            var pathFigure = new PathFigure();

            if (points.Count < 2) return pathGeometry;

            pathFigure.StartPoint = new Point(points[0].X, points[0].Y);

            // 使用贝塞尔曲线段创建平滑路径，增加插点密度
            for (int i = 0; i < points.Count - 1; i += 2)  // 从i+=3改为i+=2，增加插点密度
            {
                var p1 = i + 1 < points.Count ? new Point(points[i + 1].X, points[i + 1].Y) : pathFigure.StartPoint;
                var p2 = i + 2 < points.Count ? new Point(points[i + 2].X, points[i + 2].Y) : p1;
                var p3 = i + 3 < points.Count ? new Point(points[i + 3].X, points[i + 3].Y) : p2;

                var bezierSegment = new BezierSegment(p1, p2, p3, true);
                pathFigure.Segments.Add(bezierSegment);
            }

            pathGeometry.Figures.Add(pathFigure);
            return pathGeometry;
        }

        /// <summary>
        /// 将PathGeometry转换为StylusPoint集合
        /// </summary>
        private List<StylusPoint> ConvertPathGeometryToStylusPoints(PathGeometry pathGeometry, StylusPointCollection originalPoints)
        {
            var result = new List<StylusPoint>();
            var flattened = pathGeometry.GetFlattenedPathGeometry();

            foreach (var figure in flattened.Figures)
            {
                result.Add(new StylusPoint(figure.StartPoint.X, figure.StartPoint.Y, 0.5f));

                foreach (var segment in figure.Segments)
                {
                    if (segment is LineSegment lineSegment)
                    {
                        result.Add(new StylusPoint(lineSegment.Point.X, lineSegment.Point.Y, 0.5f));
                    }
                    else if (segment is PolyLineSegment polyLineSegment)
                    {
                        foreach (var point in polyLineSegment.Points)
                        {
                            result.Add(new StylusPoint(point.X, point.Y, 0.5f));
                        }
                    }
                }
            }

            // 保持原始压感信息
            InterpolatePressure(result, originalPoints);

            return result;
        }

        /// <summary>
        /// 插值压感信息
        /// </summary>
        private void InterpolatePressure(List<StylusPoint> smoothedPoints, StylusPointCollection originalPoints)
        {
            if (originalPoints.Count == 0 || smoothedPoints.Count == 0) return;

            for (int i = 0; i < smoothedPoints.Count; i++)
            {
                double ratio = (double)i / (smoothedPoints.Count - 1);
                int originalIndex = (int)(ratio * (originalPoints.Count - 1));
                originalIndex = Math.Max(0, Math.Min(originalIndex, originalPoints.Count - 1));

                var point = smoothedPoints[i];
                float pressure = originalPoints[originalIndex].PressureFactor;
                smoothedPoints[i] = new StylusPoint(point.X, point.Y, Math.Max(pressure, 0.1f));
            }
        }

        /// <summary>
        /// 使用GPU加速的并行贝塞尔计算
        /// </summary>
        public static StylusPoint[] ParallelBezierInterpolation(StylusPoint[] controlPoints, int segments = 32)
        {
            if (controlPoints.Length < 4) return controlPoints;

            var result = new StylusPoint[segments * (controlPoints.Length / 4)];

            Parallel.For(0, controlPoints.Length / 4, segmentIndex =>
            {
                var p0 = controlPoints[segmentIndex * 4];
                var p1 = controlPoints[segmentIndex * 4 + 1];
                var p2 = controlPoints[segmentIndex * 4 + 2];
                var p3 = controlPoints[segmentIndex * 4 + 3];

                for (int i = 0; i < segments; i++)
                {
                    double t = (double)i / (segments - 1);
                    result[segmentIndex * segments + i] = CubicBezierFast(p0, p1, p2, p3, t);
                }
            });

            return result;
        }

        /// <summary>
        /// 优化的三次贝塞尔曲线计算
        /// </summary>
        private static StylusPoint CubicBezierFast(StylusPoint p0, StylusPoint p1, StylusPoint p2, StylusPoint p3, double t)
        {
            double u = 1 - t;
            double tt = t * t;
            double uu = u * u;
            double uuu = uu * u;
            double ttt = tt * t;

            double x = uuu * p0.X + 3 * uu * t * p1.X + 3 * u * tt * p2.X + ttt * p3.X;
            double y = uuu * p0.Y + 3 * uu * t * p1.Y + 3 * u * tt * p2.Y + ttt * p3.Y;
            float pressure = (float)(p1.PressureFactor * u + p2.PressureFactor * t);

            return new StylusPoint(x, y, Math.Max(pressure, 0.1f));
        }

        /// <summary>
        /// 释放GPU相关资源。
        /// 先冻结 RenderTargetBitmap 让 WPF 停止依赖 GPU surface，再主动 Dispose 释放底层 GPU 句柄。
        /// DrawingVisual 仅在 WeakReference 由 GC 回收，无显式释放 API，依靠 GC。
        /// </summary>
        public void Dispose()
        {
            _isInitialized = false;
            try
            {
                if (_renderTarget != null)
                {
                    if (_renderTarget.CanFreeze) _renderTarget.Freeze();
                    _renderTarget.Clear();
                }
            }
            catch { }
        }
    }


}
