using Serein.Library;
using Serein.Library.Api;
using Serein.Workbench.Api;
using Serein.Workbench.Extension;
using Serein.Workbench.Tool;
using Serein.Workbench.ViewModels;
using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Shapes;
using Color = System.Windows.Media.Color;
using ColorConverter = System.Windows.Media.ColorConverter;
using Point = System.Windows.Point;

namespace Serein.Workbench.Node.View
{
    #region 连接点相关代码

    /// <summary>
    /// 连接点类型
    /// </summary>

    public class ConnectionModelBase
    {
        /// <summary>
        /// 起始节点
        /// </summary>
        public IFlowNode StartNode { get; set; }
        /// <summary>
        /// 目标节点
        /// </summary>
        public IFlowNode EndNode { get; set; }

        /// <summary>
        /// 来源于起始节点的（控制点）类型
        /// </summary>
        public JunctionType JoinTypeOfStart { get; set; }

        /// <summary>
        /// 连接到目标节点的（控制点）类型
        /// </summary>
        public JunctionType JoinTypeOfEnd { get; set; }

        /// <summary>
        /// 连接类型
        /// </summary>
        public ConnectionInvokeType Type { get; set; }
    }


    /// <summary>
    /// 连接点类型
    /// </summary>
    public interface IJunctionNode
    {
        /// <summary>
        /// 连接点所属Guid
        /// </summary>
        string BoundNodeGuid { get; }
    }

    /// <summary>
    /// 连接点
    /// </summary>
    public class JunctionNode : IJunctionNode
    {
        /// <summary>
        /// 连接点类型
        /// </summary>
        public JunctionType JunctionType { get; }
        /// <summary>
        /// 对应的视图对象
        /// </summary>
        public IFlowNode NodeModel { get; set; }
        /// <summary>
        /// 
        /// </summary>
        public string BoundNodeGuid { get => NodeModel.Guid; }
    }




























    #endregion

    /// <summary>
    /// 连接控件，表示控件的连接关系
    /// </summary>
    internal class ConnectionControl
    {
        /// <summary>
        /// 所在的画布
        /// </summary>
        public Canvas Canvas { get; }

        /// <summary>
        /// 调用方法类型，连接类型
        /// </summary>
        public ConnectionInvokeType InvokeType { get; }

        /// <summary>
        /// 目标节点控制点
        /// </summary>
        private INodeJunction EndNode;

        /// <summary>
        /// 获取参数类型，第几个参数
        /// </summary>
        public int ArgIndex { get; set; } = -1;

        /// <summary>
        /// 参数来源（决定了连接线的样式）
        /// </summary>
        public ConnectionArgSourceType ArgSourceType { get; set; }

        /// <summary>
        /// 起始控制点
        /// </summary>
        public JunctionControlBase Start { get; set; }

        /// <summary>
        /// 目标控制点
        /// </summary>
        public JunctionControlBase End { get; set; }

        /// <summary>
        /// 连接线
        /// </summary>
        public ConnectionLineShape BezierLine { get;private set; }



        private LineType LineType;

        /// <summary>
        /// 关于调用
        /// </summary>
        /// <param name="Canvas"></param>
        /// <param name="invokeType"></param>
        /// <param name="Start"></param>
        /// <param name="End"></param>
        internal ConnectionControl(Canvas Canvas,
                                ConnectionInvokeType invokeType,
                                JunctionControlBase Start,
                                JunctionControlBase End)
        {
            this.LineType = LineType.Bezier;
            this.Canvas = Canvas;
            this.InvokeType = invokeType;
            this.Start = Start;
            this.End = End;
            InitElementPoint();
        }

        /// <summary>
        ///  关于入参
        /// </summary>
        /// <param name="LineType"></param>
        /// <param name="Canvas"></param>
        /// <param name="argIndex"></param>
        /// <param name="argSourceType"></param>
        /// <param name="Start"></param>
        /// <param name="End"></param>
        /// <param name="nodeJunction"></param>
        public ConnectionControl(LineType LineType,
                                Canvas Canvas,
                                int argIndex,
                                ConnectionArgSourceType argSourceType,
                                JunctionControlBase Start,
                                JunctionControlBase End,
                                INodeJunction nodeJunction)
        {
            this.LineType = LineType;
            this.Canvas = Canvas;
            this.ArgIndex = argIndex;
            this.ArgSourceType = argSourceType;
            this.Start = Start;
            this.End = End;
            this.EndNode = nodeJunction;
            InitElementPoint();
        }

        /// <summary>
        /// 绘制
        /// </summary>
        public void InitElementPoint()
        {
            leftCenterOfEndLocation = Start.MyCenterPoint;
            rightCenterOfStartLocation = End.MyCenterPoint;
             
            (Point startPoint, Point endPoint) = RefreshPoint(Canvas, Start, End);
            var connectionType = Start.JunctionType.ToConnectyionType();
            bool isDotted;
            Brush brush;
            if(connectionType == JunctionOfConnectionType.Invoke)
            {
                brush = InvokeType.ToLineColor();
                isDotted = false;
            }
            else
            {
                brush = ArgSourceType.ToLineColor();
                isDotted = true; // 如果为参数，则绘制虚线
            }
            BezierLine = new ConnectionLineShape(LineType, startPoint, endPoint, brush, isDotted); 
            Grid.SetZIndex(BezierLine, -9999999); // 置底
            Canvas.Children.Add(BezierLine);
           
            ConfigureLineContextMenu(); //配置右键菜单
        }


        /// <summary>
        /// 配置连接曲线的右键菜单
        /// </summary>
        private void ConfigureLineContextMenu()
        {
            var contextMenu = new ContextMenu();
            contextMenu.Items.Add(WpfFuncTool.CreateMenuItem("移除该连接关系", (s, e) => Remove()));
            contextMenu.Items.Add(WpfFuncTool.CreateMenuItem("于父节点调用顺序中置顶", (s, e) => Topping()));
            BezierLine.ContextMenu = contextMenu;
        }

        /// <summary>
        /// 从画布删除
        /// </summary>
        public void RemoveOnCanvas()
        {
            Canvas.Children.Remove(BezierLine);
        }

        /// <summary>
        /// 删除该连线
        /// </summary>
        public void Remove()
        {
            /*string startGuid = Start.MyNode.Guid;
            string endGuid = End.MyNode.Guid;
            if (flowEventSerice is null) flowEventSerice = App.GetService<IFlowEEForwardingService>();
            NodeConnectChangeHandler handler = null;
            handler = (e) =>
            {
                if(e.ConnectionInvokeType == InvokeType && e.ChangeType == NodeConnectChangeEventArgs.ConnectChangeType.Remove)
                {

                }
                flowEventSerice.NodeConnectChanged -= handler;
            };
            flowEventSerice.NodeConnectChanged += handler;*/

            //
            Canvas.Children.Remove(BezierLine);
            var env = App.GetService<IFlowEnvironment>();
            var canvasGuid = ((FlowCanvasViewModel)(Canvas.DataContext)).Model.Guid;
            var jct = Start.JunctionType.ToConnectyionType();
            var jctEnd = End.JunctionType.ToConnectyionType();
            if (jct == JunctionOfConnectionType.Invoke)
            {
                env.FlowEdit.RemoveInvokeConnect(canvasGuid, Start.NodeGuid, End.NodeGuid, InvokeType);
            }
            else if (jct == JunctionOfConnectionType.Arg)
            {
                env.FlowEdit.RemoveArgSourceConnect(canvasGuid, Start.NodeGuid, End.NodeGuid, ArgIndex);
            }
        }

        /// <summary>
        /// 置顶调用关系
        /// </summary>
        public void Topping()
        {
            var env = App.GetService<IFlowEnvironment>();
            if (Start.JunctionType.ToConnectyionType() == JunctionOfConnectionType.Invoke)
            {
                env.FlowEdit.SetConnectPriorityInvoke(Start.NodeGuid, End.NodeGuid, InvokeType);
            }
        }

        /// <summary>
        /// 重新绘制
        /// </summary>
        public void RefreshLine()
        {
            if(ArgIndex > -1)
            {
                End = EndNode.GetJunctionOfArgData(ArgIndex) ?? End;
            }
            (Point startPoint, Point endPoint) = RefreshPoint(Canvas, Start, End);
            BezierLine.UpdatePoints(startPoint, endPoint);
        }


        private Point rightCenterOfStartLocation;  // 目标节点选择左侧边缘中心
        private Point leftCenterOfEndLocation;  // 起始节点选择右侧边缘中心 
        /// <summary>
        /// 刷新坐标
        /// </summary>

        private (Point startPoint, Point endPoint) RefreshPoint(Canvas canvas, FrameworkElement startElement, FrameworkElement endElement)
        {
            var startPoint = startElement.TranslatePoint(rightCenterOfStartLocation, canvas); // 获取起始节点的中心位置
            var endPoint = endElement.TranslatePoint(leftCenterOfEndLocation, canvas); // 计算终点位置
            return (startPoint, endPoint);
        }
    }








}
