﻿using System;
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEditor.Experimental.GraphView;
using UnityEngine;
using UnityEngine.UIElements;

namespace E.Story
{
    /// <summary>
    /// 故事视图元素
    /// </summary>
    public class StoryGraphView : GraphView
    {
        #region UI元素

        private StoryEditorWindow storyEditorWindow;
        private CreationSearchBox searchBox;
        private NavMap navMap;
        private VarPanel varPanel;
        private Label lblVarCount;
        private Label lblNodeCount;
        private Label lblGroupCount;
        private Label lblNoteCount;
        private Label lblScale;
        //private Label lblMousePosition;

        public VarPanel VarPanel { get => varPanel; }

        #endregion


        #region 标题重复相关变量

        private SerializableDictionary<string, NodeErrorData> duplicateUngroupedNodesRecord;
        private SerializableDictionary<string, GroupErrorData> duplicateGroupsRecord;
        private SerializableDictionary<Group, SerializableDictionary<string, NodeErrorData>> duplicateGroupedNodesRecord;
        private int duplicateTitlesAmount;

        public int DuplicateTitlesAmount { get => duplicateTitlesAmount; set => duplicateTitlesAmount = value; }

        #endregion


        #region 保存时相关变量属性

        public List<BaseGroup> Groups 
        { 
            get
            {
                // 遍历获取元素
                List<BaseGroup> groups = new();
                graphElements.ForEach(element =>
                {
                    if (element is BaseGroup group)
                    {
                        groups.Add(group);
                        return;
                    }
                });
                return groups;
            }
        }

        public List<BaseNode> Nodes 
        { 
            get
            {
                // 遍历获取元素
                List<BaseNode> baseNodes = new();
                nodes.ForEach(element =>
                {
                    if (element is BaseNode node)
                    {
                        baseNodes.Add(node);
                        return;
                    }
                });
                return baseNodes;
            }
        }

        public List<VarData> Vars 
        {
            get => varPanel.VarDatas;
        }

        public List<BaseNote> Notes
        { 
            get
            {
                // 遍历获取元素
                List<BaseNote> notes = new();
                graphElements.ForEach(element =>
                {
                    if (element is BaseNote note)
                    {
                        notes.Add(note);
                        return;
                    }
                });
                return notes;
            }
        }

        #endregion


        #region 重写方法

        /// <summary>
        /// 构造器
        /// </summary>
        /// <param name="window">编辑器窗口</param>
        public StoryGraphView(StoryEditorWindow window)
        {
            // 关联窗口类
            storyEditorWindow = window;

            // 初始化变量
            duplicateUngroupedNodesRecord = new();
            duplicateGroupsRecord = new();
            duplicateGroupedNodesRecord = new();

            // 添加元素
            AddGridBackground();
            AddManipulators();
            AddSearchBox();
            AddNavMap();
            AddVarPanel();
            AddStoryInfo();

            // 绑定回调方法
            OnOpenSearchBox();
            OnElementsReadyDelete();
            OnGroupElementsAdded();
            OnGroupElementsRemoved();
            OnGroupRenamed();
            OnGraphViewChanged();
            OnSetCanPaste();
            OnCopyElements();
            OnPasteElements();
            OnViewTransformChanged();

            // 添加默认数据
            AddDefaultNodes();
            AddDefaultVarData();

            UpdateStoryInfo();
        }

        /// <summary>
        /// 获取可连上的节点接口
        /// </summary>
        /// <param name="startPort">开始节点</param>
        /// <param name="nodeAdapter">节点适配器</param>
        /// <returns>节点列表</returns>
        public override List<Port> GetCompatiblePorts(Port startPort, NodeAdapter nodeAdapter)
        {
            List<Port> result = ports.ToList();
            result = result.Where
            (endport =>
                endport.direction != startPort.direction && endport.node != startPort.node
            ).ToList();

            return result;
        }

        /// <summary>
        /// 构建右键菜单
        /// </summary>
        /// <param name="evt"></param>
        public override void BuildContextualMenu(ContextualMenuPopulateEvent evt)
        {
            // 添加操作
            if (evt.target is GraphView || evt.target is Edge)
            {
                VisualElement temp = (VisualElement)evt.target;
                evt.menu.AppendAction("添加节点        Space", action =>
                {
                    Vector2 screenMousePosition = action.eventInfo.mousePosition + storyEditorWindow.position.position + new Vector2(50, 35);
                    nodeCreationRequest(new NodeCreationContext
                    {
                        screenMousePosition = screenMousePosition,
                        target = temp,
                        index = -1
                    });
                });
            }
            if (evt.target is GraphView || evt.target is Node)
            {
                evt.menu.AppendAction("添加分组", action =>
                {
                    CreateGroup("分组", GetLocalMousePosition(action.eventInfo.localMousePosition));
                    UpdateGroupCountInfo();
                });
            }
            if (evt.target is GraphView)
            {
                evt.menu.AppendAction("添加便签", action =>
                {
                    CreateNote("新便签", "", new Rect(GetLocalMousePosition(action.eventInfo.localMousePosition), new Vector2(200, 200)));
                    UpdateNoteCountInfo();
                });
            }

            evt.menu.AppendSeparator();

            //对象操作
            if (evt.target is GraphView || evt.target is Node || evt.target is Group)
            {
                evt.menu.AppendAction("剪切        Ctrl+X", delegate
                {
                    CutSelectionCallback();
                }, canCutSelection ? DropdownMenuAction.Status.Normal : DropdownMenuAction.Status.Disabled);
            }
            if (evt.target is GraphView || evt.target is Node || evt.target is Group)
            {
                evt.menu.AppendAction("复制        Ctrl+C", delegate
                {
                    CopySelectionCallback();
                }, canCopySelection ? DropdownMenuAction.Status.Normal : DropdownMenuAction.Status.Disabled);
            }
            if (evt.target is GraphView)
            {
                evt.menu.AppendAction("粘贴        Ctrl+V", delegate
                {
                    PasteCallback();
                }, canPaste ? DropdownMenuAction.Status.Normal : DropdownMenuAction.Status.Disabled);
            }
            if (evt.target is GraphView || evt.target is Node || evt.target is Group)
            {
                evt.menu.AppendAction("拷贝        Ctrl+D", delegate
                {
                    DuplicateSelectionCallback();
                }, canDuplicateSelection ? DropdownMenuAction.Status.Normal : DropdownMenuAction.Status.Disabled);
            }
            evt.menu.AppendSeparator();
            if (evt.target is GraphView || evt.target is Node || evt.target is Group || evt.target is Edge)
            {
                evt.menu.AppendAction("删除        Delete", delegate
                {
                    DeleteSelectionCallback(AskUser.DontAskUser);
                }, canDeleteSelection ? DropdownMenuAction.Status.Normal : DropdownMenuAction.Status.Disabled);
            }

            evt.menu.AppendSeparator();

            // 视图操作
            evt.menu.AppendAction("聚焦上一个        [", delegate
            {
                FramePrev();
            }, DropdownMenuAction.Status.Normal);
            evt.menu.AppendAction("聚焦下一个        ]", delegate
            {
                FrameNext();
            }, DropdownMenuAction.Status.Normal);
            evt.menu.AppendAction("聚焦选中        F", delegate
            {
                FrameSelection();
            }, DropdownMenuAction.Status.Normal);
            evt.menu.AppendAction("聚焦全部        A", delegate
            {
                FrameAll();
            }, DropdownMenuAction.Status.Normal);
            evt.menu.AppendAction("还原视图        O", delegate
            {
                FrameOrigin();
            }, DropdownMenuAction.Status.Normal);
        }

        #endregion


        #region 回调方法

        /// <summary>
        /// 当打开创建搜索框时
        /// </summary>
        private void OnOpenSearchBox()
        {
            nodeCreationRequest = context =>
            {
                // 指定相关联的对象
                searchBox.SetVisualElement(context.target);

                // 搜索框在鼠标点击位置显示
                SearchWindow.Open(new SearchWindowContext(context.screenMousePosition), searchBox);
            };
        }

        /// <summary>
        /// 当元素准备删除时
        /// </summary>
        private void OnElementsReadyDelete()
        {
            deleteSelection = (operationName, askUser) =>
            {
                List<BaseGroup> groupsToDelete = new();
                List<Edge> edgesToDelete = new();
                List<BaseNode> nodesToDelete = new();
                List<BaseNote> notesToDelete = new();

                foreach (GraphElement element in selection)
                {
                    // 如果删除的是节点
                    if (element is BaseNode node)
                    {
                        // 加入待删除列表
                        nodesToDelete.Add(node);
                    }

                    // 如果删除的是连线
                    else if (element is Edge edge)
                    {
                        // 加入待删除列表
                        edgesToDelete.Add(edge);
                    }

                    // 如果删除的是分组
                    else if (element is BaseGroup group)
                    {
                        // 从字典中移除分组
                        if (!StoryEditorWindow.AllowDuplicateTitles)
                            RemoveDuplicateGroupRecord(group);

                        // 加入待删除列表
                        groupsToDelete.Add(group);
                    }

                    // 如果删除的是便签
                    else if (element is BaseNote note)
                    {
                        // 加入待删除列表
                        notesToDelete.Add(note);
                    }
                }

                // 删除所有待删除的节点
                foreach (BaseNode node in nodesToDelete)
                {
                    DeleteNode(node);
                }

                // 删除所有待删除的连线
                DeleteEdges(edgesToDelete);

                // 删除所有待删除的分组
                foreach (BaseGroup group in groupsToDelete)
                {
                    DeleteGroup(group);
                }

                UpdateNodeCountInfo();
                UpdateGroupCountInfo();

                // 删除所有待删除的便签
                foreach (BaseNote note in notesToDelete)
                {
                    DeleteNote(note);
                }
                UpdateNoteCountInfo();
            };
        }

        /// <summary>
        /// 当在添加分组里添加节点时
        /// </summary>
        private void OnGroupElementsAdded()
        {
            elementsAddedToGroup = (group, elements) =>
            {
                foreach (GraphElement element in elements)
                {
                    // 如果添加的不是节点
                    if (element is not BaseNode)
                    {
                        continue;
                    }

                    BaseGroup baseGroup = (BaseGroup)group;
                    BaseNode node = (BaseNode)element;

                    // 记录节点所属分组
                    node.Group = baseGroup;

                    // 检测是否允许标题重复
                    if (!StoryEditorWindow.AllowDuplicateTitles)
                    {
                        // 更新字典
                        RemoveDuplicateUngroupedNodeRecord(node);
                        AddDuplicateGroupedNodeRecord(node, baseGroup);
                    }
                }
            };
        }

        /// <summary>
        /// 当从分组里移除节点时
        /// </summary>
        private void OnGroupElementsRemoved()
        {
            elementsRemovedFromGroup = (group, elements) =>
            {
                foreach (GraphElement element in elements)
                {
                    // 如果添加的不是节点
                    if (element is not BaseNode)
                    {
                        continue;
                    }

                    BaseGroup nodeGroup = (BaseGroup)group;
                    BaseNode node = (BaseNode)element;

                    // 清除分组信息
                    node.Group = null;

                    // 检测是否允许标题重复
                    if (!StoryEditorWindow.AllowDuplicateTitles)
                    {
                        // 更新字典
                        RemoveDuplicateGroupedNodeRecord(node, nodeGroup);
                        AddDuplicateUngroupedNodeRecord(node);
                    }
                }
            };
        }

        /// <summary>
        /// 当重命名分组时
        /// </summary>
        private void OnGroupRenamed()
        {
            groupTitleChanged = (group, newTitle) =>
            {
                BaseGroup baseGroup = (BaseGroup)group;

                // 清除无效字符
                string temp = newTitle;
                if (!StoryEditorWindow.AllowWhitespacesInTitles)
                {
                    temp = temp.RemoveWhitespaces();
                }
                if (!StoryEditorWindow.AllowSpecialCharactersInTitles)
                {
                    temp = temp.RemoveSpecialCharacters();
                }
                baseGroup.title = temp;

                // 检测是否允许标题重复
                if (StoryEditorWindow.AllowDuplicateTitles)
                {
                    // 更新标题
                    baseGroup.OldTitle = temp;
                }
                else
                {
                    RemoveDuplicateGroupRecord(baseGroup);
                    baseGroup.OldTitle = temp;
                    AddDuplicateGroupRecord(baseGroup);
                }
            };
        }

        /// <summary>
        /// 当视图发生变化
        /// </summary>
        private void OnGraphViewChanged()
        {
            graphViewChanged = (changes) =>
            {
                // 当有连线创建时
                if (changes.edgesToCreate != null)
                {
                    // 遍历所有新创建的连线，同步相应数据
                    foreach (Edge edge in changes.edgesToCreate)
                    {
                        BaseNode nextNode = (BaseNode)edge.input.node;
                        ChoiceData choiceData = (ChoiceData)edge.output.userData;
                        choiceData.NextNodeID = nextNode.GUID;
                    }
                }

                // 当有元素删除时
                if (changes.elementsToRemove != null)
                {
                    // 遍历所有删除的元素，同步相应数据
                    foreach (GraphElement element in changes.elementsToRemove)
                    {
                        if (element is not Edge)
                        {
                            continue;
                        }
                        Edge edge = (Edge)element;
                        if (edge.output == null)
                        {
                            continue;
                        }
                        ChoiceData choiceData = (ChoiceData)edge.output.userData;
                        choiceData.NextNodeID = "";
                    }
                }

                // 当有元素移动时
                if (changes.movedElements != null)
                {
                    //Debug.Log(changes.moveDelta);
                }

                return changes;
            };
        }

        /// <summary>
        /// 当设置是否可粘贴
        /// </summary>
        private void OnSetCanPaste()
        {
            //canPasteSerializedData = (data) =>
            //{
            //    return data != "data";
            //};
        }

        /// <summary>
        /// 当复制元素时
        /// </summary>
        private void OnCopyElements()
        {
            serializeGraphElements = (elements) =>
            {
                CopyDatas copyDatas = new();
                foreach (GraphElement element in elements)
                {
                    // 检测是否节点
                    if (element is BaseNode node)
                    {
                        // 过滤掉开始节点
                        if (node.Type == NodeType.Start)
                        {
                            continue;
                        }

                        NodeData nodeData = node.GetNodeData();
                        copyDatas.nodeDatas.Add(nodeData);
                    }
                    // 检测是否分组
                    else if (element is BaseGroup group)
                    {
                        GroupData groupData = group.GetGroupData();
                        copyDatas.groupDatas.Add(groupData);
                    }
                    // 检测是否便签
                    else if (element is BaseNote note)
                    {
                        NoteData noteData = note.GetNoteData();
                        copyDatas.noteDatas.Add(noteData);
                    }
                }

                // 序列化成字符串
                string temp = JsonUtility.ToJson(copyDatas, true);
                //Debug.Log(temp);
                return temp;
            };
        }

        /// <summary>
        /// 当粘贴元素时
        /// </summary>
        private void OnPasteElements()
        {
            unserializeAndPaste = (operationName, data) =>
            {
                ClearSelection();

                // 将字符串反序列化
                CopyDatas copyDatas = JsonUtility.FromJson<CopyDatas>(data);

                // 创建字典，使新元素与旧ID匹配
                Dictionary<GroupData, BaseGroup> pasteGroups = new();
                Dictionary<NodeData, BaseNode> pasteNodes = new();

                // 遍历所有分组数据，创建分组
                foreach (GroupData groupData in copyDatas.groupDatas)
                {
                    // 更新节点标题
                    string newTitle = groupData.Title;
                    // 偏移节点位置
                    Vector2 newPosition = groupData.Position + new Vector2(50, 50);

                    // 创建节点
                    BaseGroup group = CreateGroup(newTitle, newPosition, false);
                    // 加入字典
                    pasteGroups.Add(groupData, group);
                }

                // 遍历所有节点数据，创建节点
                foreach (NodeData nodeData in copyDatas.nodeDatas)
                {
                    // 更新节点标题
                    string newTitle = nodeData.Title;
                    // 偏移节点位置
                    Vector2 newPosition = nodeData.Position + new Vector2(50, 50);

                    // 创建节点
                    BaseNode node = CreateNode(newTitle, nodeData.Type, newPosition, null, false);

                    // 加入字典
                    pasteNodes.Add(nodeData, node);

                    // 复制节点信息
                    node.Note = nodeData.Note;
                    node.ChoiceDatas = DataUtility.CloneChoiceDatas(nodeData.ChoiceDatas);

                    // 检测节点类型并获取特定变量值
                    if (node.Type == NodeType.Dialogue)
                    {
                        DialogueNode dNode = node as DialogueNode;
                        dNode.RoleName = nodeData.RoleName;
                        dNode.Portrait = nodeData.Portrait;
                        dNode.SentenceDatas = DataUtility.CloneSentenceDatas(nodeData.SentenceDatas);
                    }
                    else if (node.Type == NodeType.BGI)
                    {
                        BGINode bNode = node as BGINode;
                        bNode.BGI = nodeData.BGI;
                    }
                    else if (node.Type == NodeType.EditVar)
                    {
                        EditVarNode evNode = node as EditVarNode;
                        evNode.EditVarDatas = DataUtility.CloneEditVarDatas(nodeData.EditVarDatas);
                    }

                    // 绘制节点
                    node.Draw();
                }

                // 遍历所有节点
                foreach (KeyValuePair<NodeData, BaseNode> pasteNode in pasteNodes)
                {
                    NodeData nodeData = pasteNode.Key;
                    BaseNode node = pasteNode.Value;

                    // 更新分组信息
                    if (!string.IsNullOrEmpty(nodeData.GroupID))
                    {
                        foreach (GroupData id in pasteGroups.Keys)
                        {
                            if (nodeData.GroupID == id.GUID)
                            {
                                pasteGroups[id].AddElement(node);
                                node.Title = nodeData.Title;
                                break;
                            }
                        }
                    }

                    // 创建连线
                    foreach (Port outputPort in node.outputContainer.Children())
                    {
                        ChoiceData choiceData = (ChoiceData)outputPort.userData;

                        if (string.IsNullOrEmpty(choiceData.NextNodeID))
                        {
                            continue;
                        }

                        // 获取下个节点的数据
                        NodeData nextNodeData = pasteNodes.Keys.FirstOrDefault(x => x.GUID == choiceData.NextNodeID);

                        if (nextNodeData == null)
                        {
                            choiceData.NextNodeID = "";
                            continue;
                        }

                        // 获取下个节点的输入端口
                        BaseNode nextNode = pasteNodes[nextNodeData];
                        Port nextNodeInputPort = (Port)nextNode.inputContainer.Children().First();

                        // 记录GUID
                        choiceData.NextNodeID = nextNode.GUID;

                        // 创建连线
                        CreateEdge(outputPort, nextNodeInputPort);
                    }
                    node.RefreshPorts();
                }

                UpdateGroupCountInfo();
                UpdateNodeCountInfo();

                // 遍历所有便签数据，创建便签
                foreach (NoteData noteData in copyDatas.noteDatas)
                {
                    // 偏移位置
                    Vector2 newPosition = noteData.Layout.position + new Vector2(50, 50);
                    // 创建节点
                    BaseNote note = CreateNote(noteData.Title, noteData.Content, new Rect(newPosition, noteData.Layout.size));
                }
                UpdateNoteCountInfo();
            };
        }

        /// <summary>
        /// 当视图变换时
        /// </summary>
        private void OnViewTransformChanged()
        {
            viewTransformChanged = (graphView) =>
            {
                UpdateScaleInfo();
            };
        }

        #endregion


        #region 添加小组件

        /// <summary>
        /// 添加网格背景
        /// </summary>
        private void AddGridBackground()
        {
            GridBackground gridBackground = new();
            gridBackground.StretchToParentSize();
            Insert(0, gridBackground);
        }

        /// <summary>
        /// 添加视图操作组件
        /// </summary>
        private void AddManipulators()
        {
            // 添加视图缩放组件
            //this.AddManipulator(new ContentZoomer());    // 默认是0.25~1的缩放范围
            SetupZoom(0.2f, 2.0f);      // 自定义缩放范围
            // 添加视图拖拽组件
            this.AddManipulator(new ContentDragger());
            // 添加选中对象拖拽组件
            this.AddManipulator(new SelectionDragger());
            // 添加框选组件
            this.AddManipulator(new RectangleSelector());
        }

        /// <summary>
        /// 添加搜索框
        /// </summary>
        private void AddSearchBox()
        {
            searchBox = ScriptableObject.CreateInstance<CreationSearchBox>();
            searchBox.Init(this);
        }

        /// <summary>
        /// 添加导航地图
        /// </summary>
        private void AddNavMap()
        {
            navMap = new();
            navMap.Init();
            navMap.SetPosition(new(0, 0, 200, 200));

            Add(navMap);
        }

        /// <summary>
        /// 添加小黑板
        /// </summary>
        private void AddVarPanel()
        {
            varPanel = new();
            varPanel.Init(this);
            varPanel.Draw();

            Add(varPanel);
        }

        /// <summary>
        /// 添加故事信息
        /// </summary>
        private void AddStoryInfo()
        {
            VisualElement panInfo = new();
            VisualElement panStoryInfo = new();
            lblVarCount = new();
            lblNodeCount = new();
            lblGroupCount = new();
            lblNoteCount = new();
            lblScale = new();
            //lblMousePosition = new(GetMousePostionText());

            panStoryInfo.Add(lblVarCount);
            panStoryInfo.Add(lblNodeCount);
            panStoryInfo.Add(lblGroupCount);
            panStoryInfo.Add(lblNoteCount);
            panStoryInfo.Add(lblScale);
            //panBaseInfo.Add(lblMousePosition);

            panInfo.Add(panStoryInfo);
            Add(panInfo);

            panInfo.AddClasses("info-container");
            panStoryInfo.AddClasses("row-container");
        }

        #endregion


        #region 编辑视图元素

        /// <summary>
        /// 添加默认节点
        /// </summary>
        public void AddDefaultNodes()
        {
            CreateNode("开始", NodeType.Start, new Vector2(200, 200));
            CreateNode("结束", NodeType.End, new Vector2(800, 200));

            UpdateNodeCountInfo();
        }

        /// <summary>
        /// 添加默认变量
        /// </summary>
        public void AddDefaultVarData()
        {
            VarData varData1 = new("变量一");
            VarData varData2 = new("变量二");
            VarData varData3 = new("变量三");
            varPanel.VarDatas.Add(varData1);
            varPanel.VarDatas.Add(varData2);
            varPanel.VarDatas.Add(varData3);
            varPanel.Draw();
        }

        /// <summary>
        /// 创建分组
        /// </summary>
        /// <param name="title">分组标题</param>
        /// <param name="position">分组坐标</param>
        /// <returns>分组</returns>
        public BaseGroup CreateGroup(string title, Vector2 position, bool moveSelectedNodes = true)
        {
            BaseGroup group = new(title, position);

            if (!StoryEditorWindow.AllowDuplicateTitles)
                AddDuplicateGroupRecord(group);

            AddElement(group);

            if (moveSelectedNodes)
            {
                // 如果选中了多个节点后创建分组，则将这些节点放入新的分组
                foreach (GraphElement item in selection)
                {
                    if (item is not BaseNode)
                    {
                        continue;
                    }
                    BaseNode node = (BaseNode)item;
                    group.AddElement(node);
                }
            }

            return group;
        }

        /// <summary>
        /// 创建节点
        /// </summary>
        /// <param name="title">节点标题</param>
        /// <param name="type">节点类型</param>
        /// <param name="position">节点坐标</param>
        /// <param name="group">所属分组</param>
        /// <param name="shouldDraw">是否绘制</param>
        /// <returns></returns>
        public BaseNode CreateNode(string title, NodeType type, Vector2 position, Group group = null, bool shouldDraw = true)
        {
            // 获取类型
            Type nodeType = Type.GetType($"E.Story.{type}Node");

            // 创建对应节点
            BaseNode node = Activator.CreateInstance(nodeType) as BaseNode;
            node.Init(this, title, position);

            // 是否绘制
            if (shouldDraw)
            {
                node.Draw();
            }

            if (group == null)
            {
                // 加入视图
                AddElement(node);

                // 检测是否允许标题重复
                if (!StoryEditorWindow.AllowDuplicateTitles)
                    // 将此节点标记为未分组
                    AddDuplicateUngroupedNodeRecord(node);
            }
            else
            {
                // 加入分组
                group.AddElement(node);
            }

            return node;
        }

        /// <summary>
        /// 创建连线
        /// </summary>
        /// <param name="lastOutput"></param>
        /// <param name="nextInput"></param>
        /// <returns>连线</returns>
        public Edge CreateEdge(Port lastOutput, Port nextInput)
        {
            Edge edge = lastOutput.ConnectTo(nextInput);
            AddElement(edge);
            return edge;
        }

        /// <summary>
        /// 创建便签
        /// </summary>
        /// <param name="title">标题</param>
        /// <param name="contents">内容</param>
        /// <param name="position">坐标</param>
        /// <returns>便签</returns>
        public BaseNote CreateNote(string title, string contents, Rect layout)
        {
            BaseNote note = new(title, contents, layout);
            AddElement(note);
            return note;
        }

        /// <summary>
        /// 删除分组
        /// </summary>
        /// <param name="group"></param>
        private void DeleteGroup(BaseGroup group)
        {
            List<BaseNode> groupNodes = new();

            // 遍历分组里的所有子元素，如果是节点，则将其加入待移除列表
            foreach (GraphElement groupElement in group.containedElements)
            {
                if (groupElement is BaseNode groupNode)
                {
                    groupNodes.Add(groupNode);
                }
            }

            if (groupNodes.Count == 0)
            {
                // 从视图中移除分组
                RemoveElement(group);
            }
            else
            {
                string str = $"正在删除分组“{group.title}”，其中包含 {groupNodes.Count} 个节点，是否一起删除？";
                int result = EditorUtility.DisplayDialogComplex("警告", str, "是", "取消", "否");

                // 取消
                if (result == 1)
                {
                    return;
                }

                // 从视图中移除分组
                RemoveElement(group);

                // 否
                if (result == 2)
                {
                    return;
                }

                // 是
                // 删除节点
                foreach (BaseNode node in groupNodes)
                {
                    DeleteNode(node);
                }
                UpdateNodeCountInfo();
            }
        }

        /// <summary>
        /// 删除节点
        /// </summary>
        /// <param name="node"></param>
        private void DeleteNode(BaseNode node)
        {
            // 如果删除的是开始节点
            if (node is StartNode)
            {
                string str = "不可以删除开始节点。";
                EditorUtility.DisplayDialog("警告", str, "明白");
                return;
            }

            // 如果删除的是结束节点
            if (node is EndNode)
            {
                if (GetEndNodesAmount() == 1)
                {
                    string str = "不可以删除最后一个结束节点。";
                    EditorUtility.DisplayDialog("警告", str, "明白");
                    return;
                }
            }

            // 检测是否允许标题重复
            if (!StoryEditorWindow.AllowDuplicateTitles)
                // 从字典中移除节点
                RemoveDuplicateUngroupedNodeRecord(node);

            // 移除节点的所有连线
            node.DisconnectedAllPorts();

            // 若此节点属于某个分组，则从此分组的视图中移除此节点
            node.Group?.RemoveElement(node);

            // 从视图中移除节点
            RemoveElement(node);

            // 更新节点数量信息
            lblNodeCount.text = GetNodeCountText();
        }

        /// <summary>
        /// 删除连线列表
        /// </summary>
        /// <param name="edges">连线列表</param>
        public void DeleteEdges(List<Edge> edges)
        {
            DeleteElements(edges);
        }

        /// <summary>
        /// 删除便签
        /// </summary>
        /// <param name="note">便签</param>
        public void DeleteNote(BaseNote note)
        {
            RemoveElement(note);
        }

        #endregion


        #region 标题重复相关方法

        /// <summary>
        /// 向分组字典中添加分组
        /// </summary>
        /// <param name="group"></param>
        private void AddDuplicateGroupRecord(BaseGroup group)
        {
            string groupName = group.title.ToLower();

            // 如果没有同名分组，则添加一条字典记录
            if (!duplicateGroupsRecord.ContainsKey(groupName))
            {
                GroupErrorData groupErrorData = new();
                groupErrorData.Groups.Add(group);
                duplicateGroupsRecord.Add(groupName, groupErrorData);
                return;
            }

            List<BaseGroup> groupsList = duplicateGroupsRecord[groupName].Groups;

            // 加入字典
            groupsList.Add(group);

            // 设置高亮样式
            group.SetErrorStyle();

            // 将同名的另一个节点也设置高亮样式
            if (groupsList.Count == 2)
            {
                DuplicateTitlesAmount++;

                groupsList[0].SetErrorStyle();
            }
        }

        /// <summary>
        /// 从分组字典中移除分组
        /// </summary>
        /// <param name="group"></param>
        private void RemoveDuplicateGroupRecord(BaseGroup group)
        {
            string oldGroupName = group.OldTitle.ToLower();

            List<BaseGroup> groupsList = duplicateGroupsRecord[oldGroupName].Groups;

            // 移出字典
            groupsList.Remove(group);

            // 重置样式
            group.ResetStyle();

            // 将原本同名的另一个分组也重置样式
            if (groupsList.Count == 1)
            {
                DuplicateTitlesAmount--;

                groupsList[0].ResetStyle();
                return;
            }

            // 如果同名分组都已不存在，则移除该字典记录
            if (groupsList.Count == 0)
            {
                duplicateGroupsRecord.Remove(oldGroupName);
            }
        }

        /// <summary>
        /// 向未分组节点字典中添加节点
        /// </summary>
        /// <param name="node"></param>
        public void AddDuplicateUngroupedNodeRecord(BaseNode node)
        {
            string nodeName = node.Title.ToLower();

            // 如果没有同名节点，则添加一条字典记录
            if (!duplicateUngroupedNodesRecord.ContainsKey(nodeName))
            {
                NodeErrorData nodeErrorData = new();
                nodeErrorData.Nodes.Add(node);
                duplicateUngroupedNodesRecord.Add(nodeName, nodeErrorData);
                return;
            }

            List<BaseNode> ungroupedNodes = duplicateUngroupedNodesRecord[nodeName].Nodes;

            // 加入字典
            ungroupedNodes.Add(node);

            // 设置高亮样式
            node.SetErrorStyle();

            // 将同名的另一个节点也设置高亮样式
            if (ungroupedNodes.Count == 2)
            {
                DuplicateTitlesAmount++;

                ungroupedNodes[0].SetErrorStyle();
            }
        }

        /// <summary>
        /// 从未分组节点字典中移除节点
        /// </summary>
        /// <param name="node">目标节点</param>
        public void RemoveDuplicateUngroupedNodeRecord(BaseNode node)
        {
            string nodeName = node.Title.ToLower();

            List<BaseNode> ungroupedNodesList = duplicateUngroupedNodesRecord[nodeName].Nodes;

            // 移出字典
            ungroupedNodesList.Remove(node);

            // 重置样式
            node.ResetStyle();

            // 将原本同名的另一个节点也重置样式
            if (ungroupedNodesList.Count == 1)
            {
                DuplicateTitlesAmount--;

                ungroupedNodesList[0].ResetStyle();
                return;
            }

            // 如果同名节点都已不存在，则移除该字典记录
            if (ungroupedNodesList.Count == 0)
            {
                duplicateUngroupedNodesRecord.Remove(nodeName);
            }
        }

        /// <summary>
        /// 向已分组节点字典中添加节点
        /// </summary>
        /// <param name="node">目标节点</param>
        /// <param name="group">目标分组</param>
        public void AddDuplicateGroupedNodeRecord(BaseNode node, BaseGroup group)
        {
            string nodeName = node.Title.ToLower();

            // 如果字典中不存在此分组，则添加一条分组记录
            if (!duplicateGroupedNodesRecord.ContainsKey(group))
            {
                duplicateGroupedNodesRecord.Add(group, new());
            }

            // 如果没有同名节点，则添加一条字典记录
            if (!duplicateGroupedNodesRecord[group].ContainsKey(nodeName))
            {
                NodeErrorData nodeErrorData = new();
                nodeErrorData.Nodes.Add(node);
                duplicateGroupedNodesRecord[group].Add(nodeName, nodeErrorData);
                return;
            }

            List<BaseNode> groupedNodesList = duplicateGroupedNodesRecord[group][nodeName].Nodes;

            // 加入字典
            groupedNodesList.Add(node);

            // 设置高亮样式
            node.SetErrorStyle();

            // 将同名的另一个节点也设置高亮样式
            if (groupedNodesList.Count == 2)
            {
                DuplicateTitlesAmount++;

                groupedNodesList[0].SetErrorStyle();
            }
        }

        /// <summary>
        /// 从已分组节点字典中移除节点
        /// </summary>
        /// <param name="node">目标节点</param>
        /// <param name="group">目标分组</param>
        public void RemoveDuplicateGroupedNodeRecord(BaseNode node, BaseGroup group)
        {
            string nodeName = node.Title.ToLower();

            List<BaseNode> groupedNodesList = duplicateGroupedNodesRecord[group][nodeName].Nodes;

            // 移出字典
            groupedNodesList.Remove(node);

            // 重置样式
            node.ResetStyle();

            // 将原本同名的另一个节点也重置样式
            if (groupedNodesList.Count == 1)
            {
                DuplicateTitlesAmount--;

                groupedNodesList[0].ResetStyle();
                return;
            }

            // 如果同名节点都已不存在，则移除该分组记录
            if (groupedNodesList.Count == 0)
            {
                duplicateGroupedNodesRecord[group].Remove(nodeName);

                // 如果同名分组都已不存在，则移除该字典记录
                if (duplicateGroupedNodesRecord[group].Count == 0)
                {
                    duplicateGroupedNodesRecord.Remove(group);
                }
            }

        }

        #endregion


        #region 实用方法

        /// <summary>
        /// 将节点插入连线
        /// </summary>
        /// <param name="node"></param>
        /// <param name="edge"></param>
        public void InsertNodeToEdge(BaseNode node, Edge edge)
        {
            // 获取原端口
            Port lastOutput = edge.output;
            Port nextInput = edge.input;

            // 删除原连线
            DeleteSelectionCallback(AskUser.DontAskUser);

            // 创建视图变化数据
            GraphViewChange change = new()
            {
                edgesToCreate = new(),
                elementsToRemove = new(),
            };

            // 创建左侧连线
            Edge leftEdge = CreateEdge(lastOutput, node.Input);
            change.edgesToCreate.Add(leftEdge);

            if (node.Output != null)
            {
                // 创建右侧连线
                Edge rightEdge = CreateEdge(node.Output, nextInput);
                change.edgesToCreate.Add(rightEdge);
            }

            // 触发事件
            graphViewChanged.Invoke(change);
        }

        /// <summary>
        /// 获取结束节点数量
        /// </summary>
        /// <returns>结束节点数量</returns>
        private int GetEndNodesAmount()
        {
            return graphElements.Where(e => e is EndNode).ToList().Count;
        }

        /// <summary>
        /// 获取本地鼠标坐标
        /// </summary>
        /// <param name="mousePosition">鼠标坐标</param>
        /// <param name="isSearchWindow">是否是搜索框</param>
        /// <returns></returns>
        public Vector2 GetLocalMousePosition(Vector2 mousePosition, bool isSearchWindow = false)
        {
            Vector2 worldMousePosition = mousePosition;
            if (isSearchWindow)
            {
                worldMousePosition -= storyEditorWindow.position.position;
            }

            Vector2 localMousePosition = contentViewContainer.WorldToLocal(worldMousePosition);
            return localMousePosition;
        }

        /// <summary>
        /// 清除视图
        /// </summary>
        public void ClearGraph()
        {
            graphElements.ForEach(e => RemoveElement(e));

            duplicateGroupsRecord.Clear();
            duplicateGroupedNodesRecord.Clear();
            duplicateUngroupedNodesRecord.Clear();

            DuplicateTitlesAmount = 0;

            varPanel.ClearPanel();
        }

        /// <summary>
        /// 切换小地图
        /// </summary>
        public void ToggleMiniMap()
        {
            navMap.visible = !navMap.visible;
        }

        /// <summary>
        /// 切换变量面板
        /// </summary>
        public void ToggleVarPanel()
        {
            varPanel.visible = !varPanel.visible;
        }

        /// <summary>
        /// 当变量数据更新时，更新视图
        /// </summary>
        public void OnEditVarDatas()
        {
            // 获取需要重绘的节点
            List<BaseNode> nodesToReRraw = new();
            nodes.ForEach(node =>
            {
                if (node is EditVarNode || node is BranchNode)
                {
                    nodesToReRraw.Add((BaseNode)node);
                    return;
                }
            });

            // 重绘节点
            foreach (BaseNode node in nodesToReRraw)
            {
                node.DrawExtensionContainer();
            }

            // 更新变量数量信息
            UpdateVarCountInfo();
        }

        /// <summary>
        /// 获取变量数量文本
        /// </summary>
        /// <returns>变量数量文本</returns>
        private string GetVarCountText()
        {
            return varPanel.VarDatas.Count + "变量";
        }

        /// <summary>
        /// 获取节点数量文本
        /// </summary>
        /// <returns>节点数量文本</returns>
        private string GetNodeCountText()
        {
            //int count = 0;
            //graphElements.ForEach(element =>
            //{
            //    if (element is BaseNode node)
            //    {
            //        count++;
            //        return;
            //    }
            //});
            //return count + "节点";
            return nodes.Count() + "节点";
        }

        /// <summary>
        /// 获取分组数量文本
        /// </summary>
        /// <returns>分组数量文本</returns>
        private string GetGroupCountText()
        {
            int count = 0;
            graphElements.ForEach(element =>
            {
                if (element is BaseGroup group)
                {
                    count++;
                    return;
                }
            });
            return count + "分组";
        }

        /// <summary>
        /// 获取便签数量文本
        /// </summary>
        /// <returns>便签数量文本</returns>
        private string GetNoteCountText()
        {
            int count = 0;
            graphElements.ForEach(element =>
            {
                if (element is BaseNote note)
                {
                    count++;
                    return;
                }
            });
            return count + "便签";
        }

        /// <summary>
        /// 获取缩放文本
        /// </summary>
        /// <returns>缩放文本</returns>
        private string GetScaleText()
        {
            return string.Format("{0:F2}", scale) + "x";
        }

        /// <summary>
        /// 获取鼠标坐标文本
        /// </summary>
        /// <returns>鼠标坐标文本</returns>
        //private string GetMousePostionText()
        //{
        //    Vector2 mousePos = GetLocalMousePosition();
        //    int x = (int)mousePos.x;
        //    int y = (int)mousePos.y;
        //    return $"({x},{y})";
        //}

        /// <summary>
        /// 更新故事信息
        /// </summary>
        public void UpdateStoryInfo()
        {
            UpdateVarCountInfo();
            UpdateNodeCountInfo();
            UpdateGroupCountInfo(); 
            UpdateNoteCountInfo();
            UpdateScaleInfo();
        }

        /// <summary>
        /// 更新变量数量信息
        /// </summary>
        private void UpdateVarCountInfo()
        {
            lblVarCount.text = GetVarCountText();
        }

        /// <summary>
        /// 更新节点数量信息
        /// </summary>
        public void UpdateNodeCountInfo()
        {
            lblNodeCount.text = GetNodeCountText();
        }

        /// <summary>
        /// 更新分组数量信息
        /// </summary>
        public void UpdateGroupCountInfo()
        {
            lblGroupCount.text = GetGroupCountText();
        }

        /// <summary>
        /// 更新便签数量信息
        /// </summary>
        public void UpdateNoteCountInfo()
        {
            lblNoteCount.text = GetNoteCountText();
        }

        /// <summary>
        /// 更新缩放信息
        /// </summary>
        private void UpdateScaleInfo()
        {
            lblScale.text = GetScaleText();
        }

        #endregion
    }
}