using ComPDFKit.PDFAnnotation;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media;

namespace PDF_Office.Helper
{
    public class ArrowHelper
    {
        /// <summary>
        /// 是否有开始箭头
        /// </summary>
        public bool HasStartArrow 
        { 
            get 
            {
                if (StartSharp != C_LINE_TYPE.LINETYPE_UNKNOWN && StartSharp != C_LINE_TYPE.LINETYPE_NONE)
                {
                    return true;
                }
                return false; 
            } 
        }
        /// <summary>
        /// 开始箭头是否封闭
        /// </summary>
        public bool IsStartClosed
        {
            get
            {
                if (StartSharp == C_LINE_TYPE.LINETYPE_CLOSEDARROW || StartSharp == C_LINE_TYPE.LINETYPE_RCLOSEDARROW || StartSharp == C_LINE_TYPE.LINETYPE_DIAMOND)
                {
                    return true;
                }
                return false;
            }
        }
        /// <summary>
        /// 是否有结束箭头
        /// </summary>
        public bool HasEndArrow 
        {
            get
            {
                if (EndSharp != C_LINE_TYPE.LINETYPE_UNKNOWN && EndSharp != C_LINE_TYPE.LINETYPE_NONE)
                {
                    return true;
                }
                return false;
            }
        }
        /// <summary>
        /// 结束箭头是否封闭
        /// </summary>
        public bool IsEndClosed 
        { 
            get 
            {
                if(EndSharp==C_LINE_TYPE.LINETYPE_CLOSEDARROW || EndSharp==C_LINE_TYPE.LINETYPE_RCLOSEDARROW || EndSharp == C_LINE_TYPE.LINETYPE_DIAMOND)
                {
                    return true;
                }
                return false;
            } 
        }
        /// <summary>
        /// 箭头角度
        /// </summary>
        public uint ArrowAngle { get; set; }
        /// <summary>
        /// 箭头长度
        /// </summary>
        public uint ArrowLength { get; set; }
        /// <summary>
        /// 起始点
        /// </summary>
        public Point? LineStart { get; set; }
        /// <summary>
        /// 结束点
        /// </summary>
        public Point? LineEnd { get; set; }
        /// <summary>
        /// 线段路径
        /// </summary>
        public PathGeometry Body { get; set; }
        /// <summary>
        /// 开始箭头形状
        /// </summary>
        public C_LINE_TYPE StartSharp { get; set; }
        /// <summary>
        /// 结束箭头形状
        /// </summary>
        public C_LINE_TYPE EndSharp { get; set; }
        /// <summary>
        /// 箭头帮助类
        /// </summary>
        public ArrowHelper()
        {
            Body = new PathGeometry();
            ArrowLength = 12;
            ArrowAngle = 60;
        }
        protected PathFigure CreateLineBody()
        {
            if (LineStart != null && LineEnd != null)
            {
                PathFigure lineFigure = new PathFigure();
               // lineFigure.IsClosed = true;
                lineFigure.StartPoint = (Point)LineStart;
                LineSegment linePath = new LineSegment();
                linePath.Point = (Point)LineEnd;
                //linePath.IsSmoothJoin = true;
                //linePath.IsStroked = true;
                lineFigure.Segments.Add(linePath);
                return lineFigure;
            }
            return null;
        }
        protected PathFigure CreateStartArrow()
        {
            switch (StartSharp)
            {
                case C_LINE_TYPE.LINETYPE_NONE:
                case C_LINE_TYPE.LINETYPE_UNKNOWN:
                    break;
                case C_LINE_TYPE.LINETYPE_ARROW:
                case C_LINE_TYPE.LINETYPE_CLOSEDARROW:
                    return CreateStartOpenArrow();
                case C_LINE_TYPE.LINETYPE_ROPENARROW:
                case C_LINE_TYPE.LINETYPE_RCLOSEDARROW:
                    return CreateStartReverseArrow();
                case C_LINE_TYPE.LINETYPE_BUTT:
                    return CreateStartButtArrow();
                case C_LINE_TYPE.LINETYPE_DIAMOND:
                    return CreateStartDiamondArrow();
                case C_LINE_TYPE.LINETYPE_CIRCLE:
                    return CreateStartRoundArrow();
                case C_LINE_TYPE.LINETYPE_SQUARE:
                    return CreateStartSquareArrow();
                case C_LINE_TYPE.LINETYPE_SLASH:
                    return CreateStartSlashArrow();
                default:
                    break;
            }
            return null;
        }
        protected virtual PathFigure CreateEndArrow()
        {
            switch (EndSharp)
            {
                case C_LINE_TYPE.LINETYPE_NONE:
                case C_LINE_TYPE.LINETYPE_UNKNOWN:
                    break;
                case C_LINE_TYPE.LINETYPE_ARROW:
                case C_LINE_TYPE.LINETYPE_CLOSEDARROW:
                    return CreateEndOpenArrow();
                case C_LINE_TYPE.LINETYPE_ROPENARROW:
                case C_LINE_TYPE.LINETYPE_RCLOSEDARROW:
                    return CreateEndReverseArrow();
                case C_LINE_TYPE.LINETYPE_BUTT:
                    return CreateEndButtArrow();
                case C_LINE_TYPE.LINETYPE_DIAMOND:
                    return CreateEndDiamondArrow();
                case C_LINE_TYPE.LINETYPE_CIRCLE:
                    return CreateEndRoundArrow();
                case C_LINE_TYPE.LINETYPE_SQUARE:
                    return CreateEndSquareArrow();
                case C_LINE_TYPE.LINETYPE_SLASH:
                    return CreateEndSlashArrow();
                default:
                    break;
            }
            return null;
        }
        /// <summary>
        /// 创建箭头路径
        /// </summary>
        /// <returns></returns>
        public PathGeometry BuildArrowBody()
        {
            Body.Figures.Clear();
            PathFigure lineBody = CreateLineBody();
            if (lineBody != null)
            {
                Body.Figures.Add(lineBody);
                PathFigure arrowFigure = CreateStartArrow();
                if (arrowFigure != null)
                {
                    Body.Figures.Add(arrowFigure);
                }
                arrowFigure = CreateEndArrow();
                if (arrowFigure != null)
                {
                    Body.Figures.Add(arrowFigure);
                }
            }
            return Body;
        }

        /// <summary>
        /// 绘制开始箭头
        /// </summary>
        /// <returns></returns>
        private PathFigure CreateStartOpenArrow()
        {
            if (ArrowLength == 0 || !HasStartArrow || LineStart == null || LineEnd == null || ArrowAngle == 0)
            {
                return null;
            }
            PathFigure arrowFigure = new PathFigure();
            PolyLineSegment arrowSegment = new PolyLineSegment();
            Vector lineVector = (Point)LineEnd - (Point)LineStart;
            lineVector.Normalize();
            lineVector *= ArrowLength;
            Matrix rotateMatrix = new Matrix();
            rotateMatrix.Rotate(ArrowAngle / 2);
            arrowFigure.StartPoint = (Point)LineStart + (lineVector * rotateMatrix);
            arrowSegment.Points.Add((Point)LineStart);
            rotateMatrix.Rotate(-ArrowAngle);
            arrowSegment.Points.Add((Point)LineStart + (lineVector * rotateMatrix));
            arrowFigure.Segments.Add(arrowSegment);
            arrowFigure.IsClosed = IsStartClosed;
            arrowFigure.IsFilled = IsStartClosed;
            return arrowFigure;
        }
        /// <summary>
        /// 绘制结束箭头
        /// </summary>
        /// <returns></returns>
        private PathFigure CreateEndOpenArrow()
        {
            if (ArrowLength == 0 || !HasEndArrow || LineStart == null || LineEnd == null || ArrowAngle == 0)
            {
                return null;
            }
            PathFigure arrowFigure = new PathFigure();
            PolyLineSegment arrowSegment = new PolyLineSegment();
            Vector lineVector = (Point)LineStart - (Point)LineEnd;
            lineVector.Normalize();
            lineVector *= ArrowLength;
            Matrix rotateMatrix = new Matrix();
            rotateMatrix.Rotate(ArrowAngle / 2);
            arrowFigure.StartPoint = (Point)LineEnd + (lineVector * rotateMatrix);
            arrowSegment.Points.Add((Point)LineEnd);
            rotateMatrix.Rotate(-ArrowAngle);
            arrowSegment.Points.Add((Point)LineEnd + (lineVector * rotateMatrix));
            arrowFigure.Segments.Add(arrowSegment);
            arrowFigure.IsClosed = IsEndClosed;
            arrowFigure.IsFilled = IsEndClosed;
            return arrowFigure;
        }
        /// <summary>
        /// 绘制开始箭头(逆向)
        /// </summary>
        /// <returns></returns>
        private PathFigure CreateStartReverseArrow()
        {
            if (ArrowLength == 0 || !HasStartArrow || LineStart == null || LineEnd == null || ArrowAngle == 0)
            {
                return null;
            }
            PathFigure arrowFigure = new PathFigure();
            PolyLineSegment arrowSegment = new PolyLineSegment();
            Vector lineVector = (Point)LineStart - (Point)LineEnd;
            lineVector.Normalize();
            lineVector *= ArrowLength;
            Matrix rotateMatrix = new Matrix();
            rotateMatrix.Rotate(ArrowAngle / 2);
            arrowFigure.StartPoint = (Point)LineStart + (lineVector * rotateMatrix);
            arrowSegment.Points.Add((Point)LineStart);
            rotateMatrix.Rotate(-ArrowAngle);
            arrowSegment.Points.Add((Point)LineStart + (lineVector * rotateMatrix));
            arrowFigure.Segments.Add(arrowSegment);
            arrowFigure.IsClosed = IsStartClosed;
            arrowFigure.IsFilled = IsStartClosed;
            return arrowFigure;
        }
        /// <summary>
        /// 绘制结束箭头(逆向)
        /// </summary>
        /// <returns></returns>
        private PathFigure CreateEndReverseArrow()
        {
            if (ArrowLength == 0 || !HasEndArrow || LineStart == null || LineEnd == null || ArrowAngle == 0)
            {
                return null;
            }
            PathFigure arrowFigure = new PathFigure();
            PolyLineSegment arrowSegment = new PolyLineSegment();
            Vector lineVector = (Point)LineEnd - (Point)LineStart;
            lineVector.Normalize();
            lineVector *= ArrowLength;
            Matrix rotateMatrix = new Matrix();
            rotateMatrix.Rotate(ArrowAngle / 2);
            arrowFigure.StartPoint = (Point)LineEnd + (lineVector * rotateMatrix);
            arrowSegment.Points.Add((Point)LineEnd);
            rotateMatrix.Rotate(-ArrowAngle);
            arrowSegment.Points.Add((Point)LineEnd + (lineVector * rotateMatrix));
            arrowFigure.Segments.Add(arrowSegment);
            arrowFigure.IsClosed = IsEndClosed;
            arrowFigure.IsFilled = IsEndClosed;
            return arrowFigure;
        }

        /// <summary>
        /// 绘制开始平头
        /// </summary>
        /// <returns></returns>
        private PathFigure CreateStartButtArrow()
        {
            if (ArrowLength == 0 || !HasStartArrow || LineStart == null || LineEnd == null)
            {
                return null;
            }
            PathFigure arrowFigure = new PathFigure();
            LineSegment buttSegment = new LineSegment();
            Vector lineVector = (Point)LineStart - (Point)LineEnd;
            lineVector.Normalize();
            lineVector *= ArrowLength;
            Matrix rotateMatrix = new Matrix();
            rotateMatrix.Rotate(90);
            arrowFigure.StartPoint = (Point)LineStart + (lineVector * rotateMatrix);
            rotateMatrix.Rotate(-180);
            buttSegment.Point = ((Point)LineStart + (lineVector * rotateMatrix));
            arrowFigure.Segments.Add(buttSegment);
            return arrowFigure;
        }
        /// <summary>
        /// 绘制结束平头
        /// </summary>
        /// <returns></returns>
        private PathFigure CreateEndButtArrow()
        {
            if (ArrowLength == 0 || !HasEndArrow || LineStart == null || LineEnd == null)
            {
                return null;
            }
            PathFigure arrowFigure = new PathFigure();
            LineSegment buttSegment = new LineSegment();
            Vector lineVector = (Point)LineEnd - (Point)LineStart;
            lineVector.Normalize();
            lineVector *= ArrowLength;
            Matrix rotateMatrix = new Matrix();
            rotateMatrix.Rotate(90);
            arrowFigure.StartPoint = (Point)LineEnd + (lineVector * rotateMatrix);
            rotateMatrix.Rotate(-180);
            buttSegment.Point = ((Point)LineEnd + (lineVector * rotateMatrix));
            arrowFigure.Segments.Add(buttSegment);

            return arrowFigure;
        }
        /// <summary>
        /// 绘制开始菱形
        /// </summary>
        /// <returns></returns>
        private PathFigure CreateStartDiamondArrow()
        {
            if (ArrowLength == 0 || !HasStartArrow || LineStart == null || LineEnd == null)
            {
                return null;
            }
            PathFigure arrowFigure = new PathFigure();
            PolyLineSegment arrowSegment = new PolyLineSegment();
            Vector lineVector = (Point)LineStart - (Point)LineEnd;
            lineVector.Normalize();
            lineVector *= ArrowLength;
            Matrix rotateMatrix = new Matrix();
            rotateMatrix.Rotate(45);

            Point cornerTop = (Point)LineStart + (lineVector * rotateMatrix);

            Vector turnVector = cornerTop - (Point)LineStart;
            turnVector.Normalize();
            turnVector *= ArrowLength;
            Matrix turnMatrix = new Matrix();
            turnMatrix.Rotate(-90);
            Point awayPoint = cornerTop + (turnVector * turnMatrix);

            rotateMatrix = new Matrix();
            rotateMatrix.Rotate(-45);
            Point cornerDown = (Point)LineStart + (lineVector * rotateMatrix);

            arrowFigure.StartPoint = (Point)LineStart;
            arrowSegment.Points.Add(cornerTop);
            arrowSegment.Points.Add(awayPoint);
            arrowSegment.Points.Add(cornerDown);
            arrowSegment.Points.Add((Point)LineStart);

            arrowFigure.Segments.Add(arrowSegment);
            arrowFigure.IsClosed = IsStartClosed;
            arrowFigure.IsFilled = IsStartClosed;
            return arrowFigure;
        }
        /// <summary>
        /// 绘制结束菱形
        /// </summary>
        /// <returns></returns>
        private PathFigure CreateEndDiamondArrow()
        {

            if (ArrowLength == 0 || !HasEndArrow || LineStart == null || LineEnd == null)
            {
                return null;
            }
            PathFigure arrowFigure = new PathFigure();
            PolyLineSegment arrowSegment = new PolyLineSegment();
            Vector lineVector = (Point)LineEnd - (Point)LineStart;
            lineVector.Normalize();
            lineVector *= ArrowLength;
            Matrix rotateMatrix = new Matrix();
            rotateMatrix.Rotate(45);

            Point cornerTop = (Point)LineEnd + (lineVector * rotateMatrix);

            Vector turnVector = cornerTop - (Point)LineEnd;
            turnVector.Normalize();
            turnVector *= ArrowLength;
            Matrix turnMatrix = new Matrix();
            turnMatrix.Rotate(-90);
            Point awayPoint = cornerTop + (turnVector * turnMatrix);

            rotateMatrix = new Matrix();
            rotateMatrix.Rotate(-45);
            Point cornerDown = (Point)LineEnd + (lineVector * rotateMatrix);

            arrowFigure.StartPoint = (Point)LineEnd;
            arrowSegment.Points.Add(cornerTop);
            arrowSegment.Points.Add(awayPoint);
            arrowSegment.Points.Add(cornerDown);
            arrowSegment.Points.Add((Point)LineEnd);

            arrowFigure.Segments.Add(arrowSegment);
            arrowFigure.IsClosed = IsEndClosed;
            arrowFigure.IsFilled = IsEndClosed;
            return arrowFigure;
        }
        /// <summary>
        /// 绘制开始圆形
        /// </summary>
        /// <returns></returns>
        private PathFigure CreateStartRoundArrow()
        {
            if (ArrowLength == 0 || !HasStartArrow || LineStart == null || LineEnd == null)
            {
                return null;
            }
            PathFigure arrowFigure = new PathFigure();
            Vector lineVector = (Point)LineEnd - (Point)LineStart;
            lineVector.Normalize();
            lineVector *= ArrowLength;

            Matrix rotateMatrix = new Matrix();
            rotateMatrix.Rotate(180);
            arrowFigure.StartPoint = (Point)LineStart + (lineVector * rotateMatrix);
            ArcSegment circleSegment = new ArcSegment();
            circleSegment.Point = (Point)LineStart;
            circleSegment.Size = new Size(ArrowLength / 2, ArrowLength / 2);
            arrowFigure.Segments.Add(circleSegment);
            circleSegment = new ArcSegment();
            circleSegment.Point = (Point)arrowFigure.StartPoint;
            circleSegment.Size = new Size(ArrowLength / 2, ArrowLength / 2);

            arrowFigure.Segments.Add(circleSegment);

            return arrowFigure;
        }
        /// <summary>
        /// 绘制结束圆形
        /// </summary>
        /// <returns></returns>
        private PathFigure CreateEndRoundArrow()
        {
            if (ArrowLength == 0 || !HasEndArrow || LineStart == null || LineEnd == null)
            {
                return null;
            }
            PathFigure arrowFigure = new PathFigure();
            Vector lineVector = (Point)LineStart - (Point)LineEnd;
            lineVector.Normalize();
            lineVector *= ArrowLength;

            Matrix rotateMatrix = new Matrix();
            rotateMatrix.Rotate(180);
            arrowFigure.StartPoint = (Point)LineEnd + (lineVector * rotateMatrix);
            ArcSegment circleSegment = new ArcSegment();
            circleSegment.Point = (Point)LineEnd;
            circleSegment.Size = new Size(ArrowLength / 2, ArrowLength / 2);
            arrowFigure.Segments.Add(circleSegment);
            circleSegment = new ArcSegment();
            circleSegment.Point = (Point)arrowFigure.StartPoint;
            circleSegment.Size = new Size(ArrowLength / 2, ArrowLength / 2);

            arrowFigure.Segments.Add(circleSegment);

            return arrowFigure;
        }
        /// <summary>
        /// 绘制开始方形
        /// </summary>
        /// <returns></returns>
        private PathFigure CreateStartSquareArrow()
        {
            if (ArrowLength == 0 || !HasStartArrow || LineStart == null || LineEnd == null)
            {
                return null;
            }
            PathFigure arrowFigure = new PathFigure();
            PolyLineSegment squreSegment = new PolyLineSegment();

            Vector lineVector = (Point)LineEnd - (Point)LineStart;
            lineVector.Normalize();
            lineVector *= (ArrowLength / 2);
            Matrix rotateMatrix = new Matrix();
            rotateMatrix.Rotate(90);
            arrowFigure.StartPoint = (Point)LineStart + (lineVector * rotateMatrix);
            rotateMatrix.Rotate(-180);
            Point pointCorner = (Point)LineStart + (lineVector * rotateMatrix);
            squreSegment.Points.Add(pointCorner);

            Vector moveVector = arrowFigure.StartPoint - pointCorner;
            moveVector.Normalize();
            moveVector *= (ArrowLength);
            rotateMatrix = new Matrix();
            rotateMatrix.Rotate(90);

            squreSegment.Points.Add(pointCorner + (moveVector * rotateMatrix));
            squreSegment.Points.Add(arrowFigure.StartPoint + (moveVector * rotateMatrix));
            squreSegment.Points.Add(arrowFigure.StartPoint);
            squreSegment.Points.Add((Point)LineStart);
            arrowFigure.Segments.Add(squreSegment);

            return arrowFigure;
        }
        /// <summary>
        /// 绘制结束方形
        /// </summary>
        /// <returns></returns>
        private PathFigure CreateEndSquareArrow()
        {

            if (ArrowLength == 0 || !HasEndArrow || LineStart == null || LineEnd == null)
            {
                return null;
            }
            PathFigure arrowFigure = new PathFigure();
            PolyLineSegment squreSegment = new PolyLineSegment();

            Vector lineVector = (Point)LineStart - (Point)LineEnd;
            lineVector.Normalize();
            lineVector *= (ArrowLength / 2);
            Matrix rotateMatrix = new Matrix();
            rotateMatrix.Rotate(90);
            arrowFigure.StartPoint = (Point)LineEnd + (lineVector * rotateMatrix);
            rotateMatrix.Rotate(-180);
            Point pointCorner = (Point)LineEnd + (lineVector * rotateMatrix);
            squreSegment.Points.Add(pointCorner);

            Vector moveVector = arrowFigure.StartPoint - pointCorner;
            moveVector.Normalize();
            moveVector *= (ArrowLength);
            rotateMatrix = new Matrix();
            rotateMatrix.Rotate(90);

            squreSegment.Points.Add(pointCorner + (moveVector * rotateMatrix));
            squreSegment.Points.Add(arrowFigure.StartPoint + (moveVector * rotateMatrix));
            squreSegment.Points.Add(arrowFigure.StartPoint);
            squreSegment.Points.Add((Point)LineEnd);
            arrowFigure.Segments.Add(squreSegment);

            return arrowFigure;
        }
        /// <summary>
        /// 绘制开始斜线
        /// </summary>
        /// <returns></returns>
        private PathFigure CreateStartSlashArrow()
        {
            if (ArrowLength == 0 || !HasStartArrow || LineStart == null || LineEnd == null)
            {
                return null;
            }
            PathFigure arrowFigure = new PathFigure();
            LineSegment buttSegment = new LineSegment();
            Vector lineVector = (Point)LineStart - (Point)LineEnd;
            lineVector.Normalize();
            lineVector *= ArrowLength;
            Matrix rotateMatrix = new Matrix();
            rotateMatrix.Rotate(45);
            arrowFigure.StartPoint = (Point)LineStart + (lineVector * rotateMatrix);
            rotateMatrix.Rotate(-180);
            buttSegment.Point = ((Point)LineStart + (lineVector * rotateMatrix));
            arrowFigure.Segments.Add(buttSegment);
            return arrowFigure;
        }
        /// <summary>
        /// 绘制结束斜线
        /// </summary>
        /// <returns></returns>
        private PathFigure CreateEndSlashArrow()
        {
            if (ArrowLength == 0 || !HasEndArrow || LineStart == null || LineEnd == null)
            {
                return null;
            }
            PathFigure arrowFigure = new PathFigure();
            LineSegment buttSegment = new LineSegment();
            Vector lineVector = (Point)LineEnd - (Point)LineStart;
            lineVector.Normalize();
            lineVector *= ArrowLength;
            Matrix rotateMatrix = new Matrix();
            rotateMatrix.Rotate(45);
            arrowFigure.StartPoint = (Point)LineEnd + (lineVector * rotateMatrix);
            rotateMatrix.Rotate(-180);
            buttSegment.Point = ((Point)LineEnd + (lineVector * rotateMatrix));
            arrowFigure.Segments.Add(buttSegment);

            return arrowFigure;
        }
    }
}
