using System;
using System.Collections.Generic;
//using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Shapes;

namespace MeterVision.Mark
{
    //水表图片标注管理
    public class MarkManager
    {
        private readonly Brush[] _brushes = new Brush[] { Brushes.Red, Brushes.Orange, Brushes.Yellow, Brushes.Green };
        //画布
        private Canvas _canvas;
        //最多4个点
        private List<Point> _points;
        //用来保存已绘制的图像
        private List<UIElement> _drawShapes;
        //要求的画点数(只有2、3、4三种情况)
        //1. 2个点取指针表第一个指针与最后一个指针的直线
        //2. 3个点取数字区域的选取
        //3. 4个点表盘区域的选取
        public int PointCount { get; private set; }
        //public int _curPointCount = 0;

        public bool IsMarking { get; private set; }   //正在标注标记

        //标注完成事件
        public event Action<int, List<Point>, int> FinishMark;

        public event Action<string> MarkError;

        //记录临时直线图像
        private Point lastFixedPoint;       //上一个按下的点
        private Line tempLine;         //临时线
        private bool isFirstClick = true;


        public MarkManager(Canvas canvas)
        {
            _canvas = canvas;
            _points = new List<Point>();
            _drawShapes = new List<UIElement>();
            PointCount = 0;
            IsMarking = false;
        }

        //开始标注
        public void ReadyMark(int pointCount)
        {
            //删除所有绘制的形状，不能删除表盘图像
            foreach (var shape in _drawShapes)
            {
                _canvas.Children.Remove(shape);
            }
            _drawShapes.Clear();
            _points.Clear();
            PointCount = pointCount;
            IsMarking = true;
            //_curPointCount = 0;
            InitDrawTempLine(pointCount);
        }

        //删除临时线
        private void InitDrawTempLine(int pointCount)
        {
            isFirstClick = pointCount == 3 ? true : false;
        }

        //清除标注
        public void ClearMark()
        {
            ReadyMark(PointCount);
            //IsMarking = false;
        }

        public void InitMark()
        {
            ReadyMark(0);
            IsMarking = false;
        }


        public void StopMark()
        {
            IsMarking = false;
        }

        private void AddPoint(Point point)
        {
            int index = _points.Count;
            // 绘制点击点
            Ellipse pointEllipse = new Ellipse
            {
                Width = 5,
                Height = 5,
                Fill = _brushes[index]
            };
            Canvas.SetLeft(pointEllipse, point.X - 2.5); // 调整点的中心位置
            Canvas.SetTop(pointEllipse, point.Y - 2.5);
            _canvas.Children.Add(pointEllipse);
            _drawShapes.Add(pointEllipse);

            _points.Add(point);
        }

        //更新指定位置的点坐标及标注
        private void UpdatePoint(Point point, int position)
        {
            int index = _canvas.Children.IndexOf(_drawShapes[position - 1]);
            _canvas.Children.RemoveAt(index);

            Ellipse pointEllipse = new Ellipse
            {
                Width = 5,
                Height = 5,
                Fill = _brushes[position - 1]
            };

            Canvas.SetLeft(pointEllipse, point.X - 2.5); // 调整点的中心位置
            Canvas.SetTop(pointEllipse, point.Y - 2.5);
            _canvas.Children.Insert(index, pointEllipse);

            _drawShapes.RemoveAt(position - 1);
            _drawShapes.Insert(position - 1, pointEllipse);

            _points.RemoveAt(position - 1);
            _points.Insert(position - 1, point);
        }

        //点标注
        public void PointMark(Point point)
        {
            if (IsMarking && _points.Count < PointCount)
            {
                AddPoint(point);

                if (_points.Count == PointCount)
                {
                    if (PointCount == 4)
                    {
                        //四点标表盘
                        FourPoint_DrawRectangle();
                    }
                    else if (PointCount == 3)
                    {
                        //三点画矩形
                        //删除画布中的直线元素(因为是临时的)
                        for(int i= _canvas.Children.Count-1; i>=0;i--)
                        {
                            UIElement element = _canvas.Children[i];
                            if (element is Line)
                            {
                                _canvas.Children.Remove(element);
                            }
                        }
                        ThreePoint_DrawRectangle();
                    }
                    else if (PointCount == 2)
                    {
                        TwoPoint_DrawLine();
                    }
                }//if _points.Count == PointCount
                else if(PointCount == 3 && _points.Count < PointCount)
                {
                    if (isFirstClick)
                    {
                        //第一次电子，记录起点
                        lastFixedPoint = point;
                        isFirstClick = false;
                    }
                    else
                    {
                        //固定上一条线
                        Line fixedLine = new Line
                        {
                            X1 = lastFixedPoint.X,
                            Y1 = lastFixedPoint.Y,
                            X2 = point.X,
                            Y2 = point.Y,
                            Stroke = Brushes.Red,
                            StrokeThickness = 2
                        };
                        _canvas.Children.Add(fixedLine);
                        //更新固定点
                        lastFixedPoint = point;
                    }

                    //创建新的临时线(鼠标实时跟随)
                    tempLine = new Line
                    {
                        X1 = lastFixedPoint.X,
                        Y1 = lastFixedPoint.Y,
                        X2 = lastFixedPoint.X,
                        Y2 = lastFixedPoint.Y,
                        Stroke = Brushes.Red,
                        StrokeThickness = 2
                    };
                    _canvas.Children.Add(tempLine);
                }//else if

            }//if IsMarking
        }

        //画临时线
        public void MouseDrawLine(Point point)
        {
            //第一个点,第二个点后，要画临时线
            if(IsMarking && PointCount == 3 && _points.Count >0 && _points.Count <= 2 )
            {
                if (tempLine != null)
                {
                    //Point currentPoint = e.GetPosition(MyCanvas);
                    tempLine.X2 = point.X;
                    tempLine.Y2 = point.Y;
                }
            }
        }


        // 判断三点是否共线
        private bool ArePointsCollinear(Point p1, Point p2, Point p3)
        {
            // 使用叉积判断三点是否共线
            double crossProduct = (p2.X - p1.X) * (p3.Y - p1.Y) - (p2.Y - p1.Y) * (p3.X - p1.X);
            return Math.Abs(crossProduct) < 0.0001;
        }

        //计算L12与L23的交点，作为新的第二个点
        private Point CalculatePerpendicularIntersection(Point p1, Point p2, Point p3)
        {
            double x1 = p1.X, y1 = p1.Y;
            double x2 = p2.X, y2 = p2.Y;
            double x3 = p3.X, y3 = p3.Y;

            // 计算L12的斜率
            double slopeL23 = (y3 - y2) / (x3 - x2);
            // 计算L23的斜率，L23垂直于L12，所以斜率为 -1 / slopeL12
            double slopeL12 = -1 / slopeL23;

            // L12的方程为：y = slopeL12 * x + b1
            double b1 = y1 - slopeL12 * x1;

            // L23的方程为：y = slopeL23 * x + b2
            double b2 = y3 - slopeL23 * x3;

            // 计算L12与L23的交点
            double intersectX = (b2 - b1) / (slopeL12 - slopeL23);
            double intersectY = slopeL12 * intersectX + b1;

            return new Point(intersectX, intersectY);
        }

        //计算矩形的第四个点
        private Point CalculateFourthPoint(Point p1, Point p2, Point p3)
        {
            // 计算从P1到P2的向量
            double dx1 = p2.X - p1.X;
            double dy1 = p2.Y - p1.Y;

            // 计算从P1到P3的向量
            double dx2 = p3.X - p1.X;
            double dy2 = p3.Y - p1.Y;

            // 通过平行四边形法则计算第四个点
            double x4 = p3.X - dx1;
            double y4 = p3.Y - dy1;

            return new Point(x4, y4);
        }

        // 绘制旋转矩形，连接四个顶点
        private void DrawRotatedRectangle(Point p1, Point p2, Point p3, Point p4)
        {
            // 绘制矩形的四条边
            Line line1 = new Line
            {
                X1 = p1.X,
                Y1 = p1.Y,
                X2 = p2.X,
                Y2 = p2.Y,
                Stroke = Brushes.Blue,
                StrokeThickness = 2
            };

            Line line2 = new Line
            {
                X1 = p2.X,
                Y1 = p2.Y,
                X2 = p3.X,
                Y2 = p3.Y,
                Stroke = Brushes.Blue,
                StrokeThickness = 2
            };

            Line line3 = new Line
            {
                X1 = p3.X,
                Y1 = p3.Y,
                X2 = p4.X,
                Y2 = p4.Y,
                Stroke = Brushes.Blue,
                StrokeThickness = 2
            };

            Line line4 = new Line
            {
                X1 = p4.X,
                Y1 = p4.Y,
                X2 = p1.X,
                Y2 = p1.Y,
                Stroke = Brushes.Blue,
                StrokeThickness = 2
            };

            _canvas.Children.Add(line1);
            _canvas.Children.Add(line2);
            _canvas.Children.Add(line3);
            _canvas.Children.Add(line4);
            _drawShapes.Add(line1);
            _drawShapes.Add(line2);
            _drawShapes.Add(line3);
            _drawShapes.Add(line4);
        }

        //三点画矩形
        private void ThreePoint_DrawRectangle()
        {
            //判断是否为三点共线
            if (ArePointsCollinear(_points[0], _points[1], _points[2]))
            {
                ReadyMark(PointCount);
                MarkError?.Invoke("三个点共线，无效的标注");
                return;
            }

            //计算新的第二个点
            Point newSecondPoint = CalculatePerpendicularIntersection(_points[0], _points[1], _points[2]);
            UpdatePoint(newSecondPoint, 2); //第2个位置更新
            //AddPoint(newSecondPoint);


            // 计算第四个点（矩形的另一个角）
            Point fourthPoint = CalculateFourthPoint(_points[0], newSecondPoint, _points[2]);
            AddPoint(fourthPoint);  //增加第四个位置


            DrawRotatedRectangle(_points[0], newSecondPoint, _points[2], fourthPoint);

            IsMarking = false;
            FinishMark?.Invoke(3, _points, 0);
        }

        //四点标记表盘
        private void FourPoint_DrawRectangle()
        {
            //通过标记的四个点来计算矩形的坐标
            double xMin = Math.Min(Math.Min(_points[0].X, _points[1].X), Math.Min(_points[2].X, _points[3].X));
            double yMin = Math.Min(Math.Min(_points[0].Y, _points[1].Y), Math.Min(_points[2].Y, _points[3].Y));

            double xMax = Math.Max(Math.Max(_points[0].X, _points[1].X), Math.Max(_points[2].X, _points[3].X));
            double yMax = Math.Max(Math.Max(_points[0].Y, _points[1].Y), Math.Max(_points[2].Y, _points[3].Y));

            double width = Math.Abs(xMax - xMin);
            double height = Math.Abs(yMax - yMin);

            //画矩形
            var rectangle = new Rectangle
            {
                Stroke = Brushes.Blue,
                StrokeThickness = 2,
                Fill = Brushes.Transparent,
                Width = width,
                Height = height
            };

            _canvas.Children.Add(rectangle);
            Canvas.SetLeft(rectangle, xMin);
            Canvas.SetTop(rectangle, yMin);

            _drawShapes.Add(rectangle);

            List<Point> points = new List<Point>
            {
                new Point(xMin,yMin),new Point(xMax,yMax)
            };


            IsMarking = false;
            FinishMark?.Invoke(2, points, 0);
        }

        //2点标记直线
        private void TwoPoint_DrawLine()
        {
            Line line = new Line
            {
                X1 = _points[0].X,
                Y1 = _points[0].Y,
                X2 = _points[1].X,
                Y2 = _points[1].Y,
                Stroke = Brushes.Blue,
                StrokeThickness = 2
            };
            _canvas.Children.Add(line);
            _drawShapes.Add(line);

            IsMarking = false;
            FinishMark?.Invoke(3, _points, 0);
        }
        //-------------------------------------------------------------------------
    }
}
