using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using System.Windows.Input;
using System.Windows.Media;
using AIStudio.Wpf.DiagramDesigner;
using AIStudio.Wpf.DiagramDesigner.Geometrys;
using AIStudio.Wpf.Mind.Controls;
using AIStudio.Wpf.Mind.Helpers;
using AIStudio.Wpf.Mind.Models;

namespace AIStudio.Wpf.Mind.ViewModels
{
    public class MindDiagramViewModel : DiagramViewModel, IMindDiagramViewModel
    {
        #region
        private MindType _mindType = MindType.Mind;
        public MindType MindType
        {
            get
            {
                return _mindType;
            }
            set
            {
                SetProperty(ref _mindType, value);
            }
        }

        private MindTheme _mindTheme;
        public MindTheme MindTheme
        {
            get
            {
                return _mindTheme;
            }
            set
            {
                SetProperty(ref _mindTheme, value);
            }
        }

        public List<MindNode> RootItems
        {
            get
            {
                return Items.OfType<MindNode>().Where(p => p.NodeLevel == 0).ToList();
            }
        }

        public MindNode MindSelectedItem
        {
            get
            {
                return SelectedItem as MindNode;
            }
        }

        public List<MindNode> MindSelectedItems
        {
            get
            {
                return SelectedItems.OfType<MindNode>().ToList();
            }
        }

        private LinkInfo _linkInfo = new LinkInfo();
        public LinkInfo LinkInfo
        {
            get
            {
                return _linkInfo;
            }
            set
            {
                SetProperty(ref _linkInfo, value);
            }
        }

        private ImageInfo _imageInfo = new ImageInfo();
        public ImageInfo ImageInfo
        {
            get
            {
                return _imageInfo;
            }
            set
            {
                SetProperty(ref _imageInfo, value);
            }
        }

        private string _remark;
        public string Remark
        {
            get
            {
                return _remark;
            }
            set
            {
                SetProperty(ref _remark, value);
            }
        }
        #endregion

        #region 命令        
        private ICommand _addRootCommand;
        public ICommand AddRootCommand
        {
            get
            {
                return this._addRootCommand ?? (this._addRootCommand = new SimpleCommand(ExecuteEnable, this.ExecuteAddRootCommand));
            }
        }

        private ICommand _addParentCommand;
        public ICommand AddParentCommand
        {
            get
            {
                return this._addParentCommand ?? (this._addParentCommand = new SimpleCommand(MindLevelEnable, this.ExecuteAddParentCommand));
            }
        }

        private ICommand _addChildCommand;
        public new ICommand AddChildCommand
        {
            get
            {
                return this._addChildCommand ?? (this._addChildCommand = new SimpleCommand(MindExecuteEnable, this.ExecuteAddChildCommand));
            }
        }

        private ICommand _AddPearCommand;
        public ICommand AddPearCommand
        {
            get
            {
                return this._AddPearCommand ?? (this._AddPearCommand = new SimpleCommand(MindLevelEnable, this.ExecuteAddPearCommand));
            }
        }

        private ICommand _moveForwardCommand;
        public ICommand MoveForwardCommand
        {
            get
            {
                return this._moveForwardCommand ?? (this._moveForwardCommand = new SimpleCommand(MindExecuteEnable, ExecuteMoveForwardCommand));
            }
        }

        private ICommand _moveBackCommand;
        public ICommand MoveBackCommand
        {
            get
            {
                return this._moveBackCommand ?? (this._moveBackCommand = new SimpleCommand(MindExecuteEnable, ExecuteMoveBackCommand));
            }
        }

        private ICommand _exportCommand;
        public ICommand ExportCommand
        {
            get
            {
                return this._exportCommand ?? (this._exportCommand = new SimpleCommand(MindExecuteEnable, ExecuteExportCommand));
            }
        }

        private ICommand _importCommand;
        public ICommand ImportCommand
        {
            get
            {
                return this._importCommand ?? (this._importCommand = new SimpleCommand(MindExecuteEnable, ExecuteImportCommand));
            }
        }

        private ICommand _selectBrotherCommand;
        public ICommand SelectBrotherCommand
        {
            get
            {
                return this._selectBrotherCommand ?? (this._selectBrotherCommand = new SimpleCommand(MindLevelEnable, ExecuteSelectBrotherCommand));
            }
        }

        private ICommand _selectPearCommand;
        public ICommand SelectPearCommand
        {
            get
            {
                return this._selectPearCommand ?? (this._selectPearCommand = new SimpleCommand(MindLevelEnable, ExecuteSelectPearCommand));
            }
        }

        private ICommand _selectRouteCommand;
        public ICommand SelectRouteCommand
        {
            get
            {
                return this._selectRouteCommand ?? (this._selectRouteCommand = new SimpleCommand(MindLevelEnable, ExecuteSelectRouteCommand));
            }
        }

        private ICommand _selectChildCommand;
        public ICommand SelectChildCommand
        {
            get
            {
                return this._selectChildCommand ?? (this._selectChildCommand = new SimpleCommand(MindLevelEnable, ExecuteSelectChildCommand));
            }
        }

        private ICommand _addLinkCommand;
        public ICommand AddLinkCommand
        {
            get
            {
                return this._addLinkCommand ?? (this._addLinkCommand = new SimpleCommand(MindExecuteEnable, ExecuteAddLinkCommand));
            }
        }

        private ICommand _removeLinkCommand;
        public ICommand RemoveLinkCommand
        {
            get
            {
                return this._removeLinkCommand ?? (this._removeLinkCommand = new SimpleCommand(MindExecuteEnable, ExecuteRemoveLinkCommand));
            }
        }

        private ICommand _addImageCommand;
        public ICommand AddImageCommand
        {
            get
            {
                return this._addImageCommand ?? (this._addImageCommand = new SimpleCommand(MindExecuteEnable, ExecuteAddImageCommand));
            }
        }

        private ICommand _removeImageCommand;
        public ICommand RemoveImageCommand
        {
            get
            {
                return this._removeImageCommand ?? (this._removeImageCommand = new SimpleCommand(MindExecuteEnable, ExecuteRemoveImageCommand));
            }
        }

        private ICommand _addRemarkCommand;
        public ICommand AddRemarkCommand
        {
            get
            {
                return this._addRemarkCommand ?? (this._addRemarkCommand = new SimpleCommand(MindExecuteEnable, ExecuteAddRemarkCommand));
            }
        }

        private ICommand _removeRemarkCommand;
        public ICommand RemoveRemarkCommand
        {
            get
            {
                return this._removeRemarkCommand ?? (this._removeRemarkCommand = new SimpleCommand(MindExecuteEnable, ExecuteRemoveRemarkCommand));
            }
        }

        private ICommand _addPriorityCommand;
        public ICommand AddPriorityCommand
        {
            get
            {
                return this._addPriorityCommand ?? (this._addPriorityCommand = new SimpleCommand(MindExecuteEnable, ExecuteAddPriorityCommand));
            }
        }

        private ICommand _addRatioCommand;
        public ICommand AddRatioCommand
        {
            get
            {
                return this._addRatioCommand ?? (this._addRatioCommand = new SimpleCommand(MindExecuteEnable, ExecuteAddRatioCommand));
            }
        }

        private ICommand _addTagCommand;
        public ICommand AddTagCommand
        {
            get
            {
                return this._addTagCommand ?? (this._addTagCommand = new SimpleCommand(MindExecuteEnable, ExecuteAddTagCommand));
            }
        }

        private ICommand _removeTagCommand;
        public ICommand RemoveTagCommand
        {
            get
            {
                return this._removeTagCommand ?? (this._removeTagCommand = new SimpleCommand(MindExecuteEnable, ExecuteRemoveTagCommand));
            }
        }

        private ICommand _clearThemeCommand;
        public ICommand ClearThemeCommand
        {
            get
            {
                return this._clearThemeCommand ?? (this._clearThemeCommand = new SimpleCommand(ExecuteEnable, this.ExecutedClearThemeCommand));
            }
        }

        private ICommand _copyThemeCommand;
        public ICommand CopyThemeCommand
        {
            get
            {
                return this._copyThemeCommand ?? (this._copyThemeCommand = new SimpleCommand(ExecuteEnable, this.ExecutedCopyThemeCommand));
            }
        }

        private ICommand _pasteThemeCommand;
        public ICommand PasteThemeCommand
        {
            get
            {
                return this._pasteThemeCommand ?? (this._pasteThemeCommand = new SimpleCommand(ExecuteEnable, this.ExecutedPasteThemeCommand));
            }
        }

        private ICommand _expand2LevelCommand;
        public ICommand Expand2LevelCommand
        {
            get
            {
                return this._expand2LevelCommand ?? (this._expand2LevelCommand = new SimpleCommand(ExecuteEnable, this.ExecutedExpand2LevelCommand));
            }
        }
        #endregion

        #region ctor和初始化
        public MindDiagramViewModel()
        {

        }

        public override void Init(bool initNew)
        {
            if (initNew)
            {
                if (Items.Count == 0)
                {
                    AddRootItem();
                }
            }
            ResetChildren(RootItems);
            RootItems?.ForEach(p => p.UpdatedLayout());
            base.Init(initNew);
        }

        private MindNode AddRootItem()
        {
            ClearSelectedItems();
            MindNode level1node = new MindNode(this) { Root = this, Id = Guid.NewGuid(), Text = "思维导图", MindType = MindType, MindTheme = MindTheme };
            level1node.InitLayout(true);
            Items.Add(level1node);
            level1node.IsSelected = true;

            Move(level1node, null, null);

            return level1node;
        }

        protected override void ExecutedResetLayoutCommand(object obj)
        {
            foreach (var item in Items.OfType<MindNode>())
            {
                item.Offset = new DiagramDesigner.Geometrys.PointBase();
            }

            RootItems?.ForEach(p => p.UpdatedLayout());
        }

        private void ResetChildren(IEnumerable<MindNode> parents)
        {
            if (parents == null)
                return;

            foreach (var parent in parents)
            {
                parent.Children = new System.Collections.ObjectModel.ObservableCollection<MindNode>(Items.OfType<MindNode>().Where(p => p.ParentId == parent.Id));
                foreach (var item in Items.OfType<MindNode>().Where(p => p.ParentId == parent.Id).ToList())
                {
                    item.Parent = parent;
                    item.InitLayout(false);
                    item.InitConnectionLayout();
                }
                ResetChildren(parent.Children);
            }
        }
        #endregion

        #region 命令使能
        public bool MindExecuteEnable(object para)
        {
            if (ExecuteEnable(para) == false) return false;

            if (SelectedItem is MindNode) return true;

            return false;
        }

        private bool MindLevelEnable(object obj)
        {
            if (MindExecuteEnable(obj) == false) return false;

            return (SelectedItem as MindNode).NodeLevel != 0;
        }
        #endregion

        #region 属性改变 
        protected override void DiagramViewModel_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            base.DiagramViewModel_PropertyChanged(sender, e);
            if (e.PropertyName == nameof(MindType))
            {
                if (e is ValuePropertyChangedEventArgs valuePropertyChangedEventArgs)
                {
                    ChangeMindType((MindType)valuePropertyChangedEventArgs.OldValue, (MindType)valuePropertyChangedEventArgs.NewValue);
                }
            }
            else if (e.PropertyName == nameof(MindTheme))
            {
                if (e is ValuePropertyChangedEventArgs valuePropertyChangedEventArgs)
                {
                    ChangeMindTheme((MindTheme)valuePropertyChangedEventArgs.OldValue, (MindTheme)valuePropertyChangedEventArgs.NewValue);
                }
            }
        }

        protected override void Item_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            base.Item_PropertyChanged(sender, e);
            if (e.PropertyName == "IsSelected")
            {
                if (e is ValuePropertyChangedEventArgs valuePropertyChangedEventArgs)
                {
                    LinkInfo = new LinkInfo(MindSelectedItem?.LinkInfo);
                    ImageInfo = new ImageInfo(MindSelectedItem?.ImageInfo);
                    Remark = MindSelectedItem?.Remark;
                    _mindType = MindSelectedItem?.MindType ?? RootItems.FirstOrDefault()?.MindType ?? MindType.Mind;
                    _mindTheme = MindSelectedItem?.MindTheme ?? RootItems.FirstOrDefault()?.MindTheme ?? MindTheme.SkyBlue;
                    RaisePropertyChanged(nameof(MindType));
                    RaisePropertyChanged(nameof(MindTheme));
                }
            }
        }
        #endregion

        #region 新增,删除
        public void ExecuteAddRootCommand(object parameter)
        {
            MindNode rootitem = null;
            DoCommandManager.DoNewCommand(this.ToString(),
                () => {
                    rootitem = AddRootItem();
                },
                () => {
                    if (rootitem != null)
                    {
                        Delete(rootitem);
                    }
                });

        }

        public void ExecuteAddChildCommand(object parameter)
        {
            List<MindNode> items = new List<MindNode>();
            List<MindNode> newitems = new List<MindNode>();
            if (parameter is MindNode node)
            {
                items.Add(node);
            }
            else if (parameter is IEnumerable<MindNode> para)
            {
                items.AddRange(para);
            }
            else
            {
                items.AddRange(SelectedItems.OfType<MindNode>());
            }

            DoCommandManager.DoNewCommand(this.ToString(),
                () => {

                    foreach (var item in items)
                    {
                        var newitem = new MindNode(this) { Text = $"分支主题{item.Children.Count + 1}" };
                        newitem.AddTo(item);
                        newitems.Add(newitem);
                    }

                    items.Select(p => p.RootNode).Distinct().ToList().ForEach(p => p.UpdatedLayout());
                },
                () => {
                    foreach (var item in newitems)
                    {
                        item.RemoveFrom();
                    }

                    items.Select(p => p.RootNode).Distinct().ToList().ForEach(p => p.UpdatedLayout());
                });

        }

        public void ExecuteAddParentCommand(object parameter)
        {
            List<MindNode> items = new List<MindNode>();
            List<MindNode> newitems = new List<MindNode>();
            if (parameter is MindNode node)
            {
                items.Add(node);
            }
            else if (parameter is IEnumerable<MindNode> para)
            {
                items.AddRange(para);
            }
            else
            {
                items.AddRange(SelectedItems.OfType<MindNode>());
            }

            DoCommandManager.DoNewCommand(this.ToString(),
                 () => {
                     foreach (var item in items)
                     {
                         if (item.ParentNode == null)
                             continue;

                         int index = item.ParentNode.Children.IndexOf(item);

                         var newitem = new MindNode(this) { Text = $"分支主题{index + 1}" };
                         newitem.AddTo(item.ParentNode, index);
                         item.RemoveFrom();
                         item.AddTo(newitem, -1, false);
                         newitems.Add(newitem);
                     }

                     items.Select(p => p.RootNode).Distinct().ToList().ForEach(p => p.UpdatedLayout());
                 },
                 () => {
                     foreach (var item in items)
                     {
                         if (item.ParentNode == null || item.ParentNode.ParentNode == null)
                             continue;

                         var parent = item.ParentNode;
                         int index = item.ParentNode.ParentNode.Children.IndexOf(item.ParentNode);

                         item.RemoveFrom();
                         parent.RemoveFrom();
                         item.AddTo(parent.ParentNode, index);
                     }

                     items.Select(p => p.RootNode).Distinct().ToList().ForEach(p => p.UpdatedLayout());
                 });
        }

        public void ExecuteAddPearCommand(object parameter)
        {
            List<MindNode> items = new List<MindNode>();
            List<MindNode> newitems = new List<MindNode>();
            if (parameter is MindNode node)
            {
                items.Add(node);
            }
            else if (parameter is IEnumerable<MindNode> para)
            {
                items.AddRange(para);
            }
            else
            {
                items.AddRange(SelectedItems.OfType<MindNode>());
            }

            DoCommandManager.DoNewCommand(this.ToString(),
                 () => {
                     foreach (var item in items)
                     {
                         if (item.ParentNode == null)
                         {
                             var newitem = new MindNode(this) { Text = $"分支主题{item.Children.Count + 1}" };
                             newitem.AddTo(item);
                             newitems.Add(newitem);
                         }
                         else
                         {
                             int index = item.ParentNode.Children.IndexOf(item);
                             var newitem = new MindNode(this) { Text = $"分支主题{item.ParentNode.Children.Count + 1}" };
                             item.IsSelected = false;
                             newitem.AddTo(item.ParentNode, index + 1);
                             newitems.Add(newitem);
                         }
                     }

                     items.Select(p => p.RootNode).Distinct().ToList().ForEach(p => p.UpdatedLayout());
                 },
                 () => {
                     foreach (var item in newitems)
                     {
                         item.RemoveFrom();
                         item.UpdatedLayout();
                     }

                     items.Select(p => p.RootNode).Distinct().ToList().ForEach(p => p.UpdatedLayout());
                 });
        }

        public override bool Next()
        {
            if (SelectedItems.Count > 0)
            {
                ExecuteAddPearCommand(null);
                return true;
            }
            else
            {
                return false;
            }
        }

        private void ExecuteMoveBackCommand(object parameter)
        {
            List<MindNode> items = new List<MindNode>();
            if (parameter is MindNode node)
            {
                items.Add(node);
            }
            else if (parameter is IEnumerable<MindNode> para)
            {
                items.AddRange(para);
            }
            else
            {
                items.AddRange(SelectedItems.OfType<MindNode>());
            }

            DoCommandManager.DoNewCommand(this.ToString(),
                () => {
                    MoveBack(items);
                },
                () => {
                    MoveForward(items);
                });
        }

        private void ExecuteMoveForwardCommand(object parameter)
        {
            List<MindNode> items = new List<MindNode>();
            List<MindNode> newitems = new List<MindNode>();
            if (parameter is MindNode node)
            {
                items.Add(node);
            }
            else if (parameter is IEnumerable<MindNode> para)
            {
                items.AddRange(para);
            }
            else
            {
                items.AddRange(SelectedItems.OfType<MindNode>());
            }

            DoCommandManager.DoNewCommand(this.ToString(),
              () => {
                  MoveForward(items);
              },
              () => {
                  MoveBack(items);
              });
        }

        private void ExecuteExportCommand(object parameter)
        {
            if (parameter is MindNode node)
            {

            }
            else
            {
                node = SelectedItem as MindNode;
            }

            if (node != null)
            {
                var output = node.GetChildrenText(true);
                var window = new NodeDTSWindow("导出节点", output);
                window.ShowDialog();
            }
        }

        private void ExecuteImportCommand(object parameter)
        {
            if (parameter is MindNode node)
            {

            }
            else
            {
                node = SelectedItem as MindNode;
            }

            if (node != null)
            {
                var window = new NodeDTSWindow("导入节点", "");
                if (window.ShowDialog() == true)
                {
                    List<MindNode> newitems = new List<MindNode>();
                    DoCommandManager.DoNewCommand(this.ToString(),
                    () => {
                        var content = window.ContentString;
                        var lines = content.Split(new string[] { "\n", "\r" }, StringSplitOptions.RemoveEmptyEntries);
                        MindNode lastnode = node;
                        foreach (var line in lines)
                        {
                            int level = Regex.Matches(line, "\t").Count + node.NodeLevel + 1;
                            string text = line.Replace("\t", "");
                            var newitem = new MindNode(this) { Text = text };
                            while (lastnode.NodeLevel != level - 1)
                            {
                                lastnode = lastnode.ParentNode;
                            }
                            if (lastnode == null)
                            {
                                continue;
                            }
                            newitem.AddTo(lastnode, isSelected: false);
                            lastnode = newitem;
                            newitems.Add(newitem);
                        }
                        node.UpdatedLayout();
                    },
                    () => {
                        foreach (var item in newitems)
                        {
                            item.RemoveFrom();
                        }
                        node.UpdatedLayout();
                    });
                }
            }
        }

        private void MoveBack(List<MindNode> items)
        {
            foreach (var item in items)
            {
                if (item.ParentNode == null)
                    continue;

                var parent = item.ParentNode;
                int index = parent.Children.IndexOf(item);

                if (index < parent.Children.Count - 1)
                {
                    item.RemoveFrom();
                    item.AddTo(parent, index + 1);
                }
            }
            items.Select(p => p.RootNode).Distinct().ToList().ForEach(p => p.UpdatedLayout());
        }

        private void MoveForward(List<MindNode> items)
        {
            foreach (var item in items)
            {
                if (item.ParentNode == null)
                    continue;

                var parent = item.ParentNode;
                int index = parent.Children.IndexOf(item);

                if (index > 0)
                {
                    item.RemoveFrom();
                    item.AddTo(parent, index - 1);
                }
            }
            items.Select(p => p.RootNode).Distinct().ToList().ForEach(p => p.UpdatedLayout());
        }

        protected override void ExecuteDeleteCommand(object parameter)
        {
            List<MindNode> items = new List<MindNode>();
            List<SelectableDesignerItemViewModelBase> others = new List<SelectableDesignerItemViewModelBase>();
            if (parameter is MindNode node)
            {
                items.Add(node);
            }
            else if (parameter is IEnumerable<MindNode> para)
            {
                items.AddRange(para);
            }
            else
            {
                items.AddRange(SelectedItems.OfType<MindNode>());

                others = SelectedItems.Where(p => !(p is MindNode)).ToList();
            }

            if (items.Any())
            {
                //把子节点都加上
                foreach (var item in items.ToList())
                {
                    var children = item.GetChildren();
                    items.AddRange(children);
                }
                //去重
                items = items.Distinct().ToList();


                Dictionary<MindNode, Tuple<int, MindNode>> indexs = items.ToDictionary(p => p, p => new Tuple<int, MindNode>(p.ParentNode != null ? p.ParentNode.Children.IndexOf(p) : 0, p.ParentNode));
                DoCommandManager.DoNewCommand(this.ToString(),
                  () => {

                      foreach (var item in items.ToList())
                      {
                          item.RemoveFrom();
                      }

                      if (others.Any())
                      {
                          base.Delete(others);
                      }

                      items.Select(p => p.RootNode).Distinct().ToList().ForEach(p => p.UpdatedLayout());
                  },
                  () => {
                      if (others.Any())
                      {
                          base.Add(others);
                      }

                      foreach (var item in items)
                      {
                          item.AddTo(indexs[item].Item2, indexs[item].Item1, false);
                          if (item.ParentId == Guid.Empty)
                          {
                              item.Offset = new PointBase();
                          }
                      }

                      items.Select(p => p.RootNode).Distinct().ToList().ForEach(p => p.UpdatedLayout());
                  });
            }
        }

        #endregion

        #region 复制,粘贴
        protected override void FixOtherInfo(List<SelectableDesignerItemViewModelBase> items)
        {
            List<MindNode> parents = new List<MindNode>();
            foreach (var item in items.OfType<MindNode>())
            {
                var parent = Items.OfType<MindNode>().FirstOrDefault(p => p.Id == item.ParentId);
                if (parent != null && !items.Contains(parent))
                {
                    parents.Add(parent);
                }
                else if (item.ParentId == Guid.Empty)
                {
                    //item.Offset = new PointBase(item.Offset.X - OffsetX, item.Offset.Y - OffsetY);
                    parents.Add(item);
                    item.InitLayout(false);
                }
            }
            ResetChildren(parents);
            parents.ForEach(p => p.UpdatedLayout());
        }
        #endregion

        #region 附加信息
        private void ExecuteAddLinkCommand(object obj)
        {
            if (obj is object[] array && array.Length == 2)
            {
                if (string.IsNullOrEmpty(array[0]?.ToString()))
                {
                    return;
                }
                Dictionary<MindNode, LinkInfo> infos = SelectedItems.OfType<MindNode>().ToDictionary(p => p, p => p.LinkInfo);
                DoCommandManager.DoNewCommand(this.ToString(),
                  () => {
                      SelectedItems.OfType<MindNode>().ToList().ForEach(p => {
                          p.LinkInfo = new LinkInfo(array[0]?.ToString(), array[1]?.ToString());
                      });
                  },
                  () => {
                      foreach (var linkInfo in infos)
                      {
                          linkInfo.Key.LinkInfo = linkInfo.Value;
                      }
                  });
            }
        }

        private void ExecuteRemoveLinkCommand(object obj)
        {
            Dictionary<MindNode, LinkInfo> infos = SelectedItems.OfType<MindNode>().ToDictionary(p => p, p => p.LinkInfo);

            DoCommandManager.DoNewCommand(this.ToString(),
              () => {
                  SelectedItems.OfType<MindNode>().ToList().ForEach(p => {
                      p.LinkInfo = null;
                  });
              },
              () => {
                  foreach (var info in infos)
                  {
                      info.Key.LinkInfo = info.Value;
                  }
              });
        }

        private void ExecuteAddImageCommand(object obj)
        {
            if (obj is object[] array && array.Length == 2)
            {
                if (string.IsNullOrEmpty(array[0]?.ToString()))
                {
                    return;
                }
                Dictionary<MindNode, ImageInfo> infos = SelectedItems.OfType<MindNode>().ToDictionary(p => p, p => p.ImageInfo);
                DoCommandManager.DoNewCommand(this.ToString(),
                  () => {
                      SelectedItems.OfType<MindNode>().ToList().ForEach(p => {
                          p.ImageInfo = new ImageInfo(array[0]?.ToString(), array[1]?.ToString());
                      });
                  },
                  () => {
                      foreach (var info in infos)
                      {
                          info.Key.ImageInfo = info.Value;
                      }
                  });
            }
        }

        private void ExecuteRemoveImageCommand(object obj)
        {
            Dictionary<MindNode, ImageInfo> infos = SelectedItems.OfType<MindNode>().ToDictionary(p => p, p => p.ImageInfo);

            DoCommandManager.DoNewCommand(this.ToString(),
              () => {
                  SelectedItems.OfType<MindNode>().ToList().ForEach(p => {
                      p.ImageInfo = null;
                  });
              },
              () => {
                  foreach (var info in infos)
                  {
                      info.Key.ImageInfo = info.Value;
                  }
              });
        }

        private void ExecuteAddRemarkCommand(object obj)
        {

            if (string.IsNullOrEmpty(obj?.ToString()))
            {
                return;
            }
            Dictionary<MindNode, string> infos = SelectedItems.OfType<MindNode>().ToDictionary(p => p, p => p.Remark);
            DoCommandManager.DoNewCommand(this.ToString(),
              () => {
                  SelectedItems.OfType<MindNode>().ToList().ForEach(p => {
                      p.Remark = obj?.ToString();
                  });
              },
              () => {
                  foreach (var info in infos)
                  {
                      info.Key.Remark = info.Value;
                  }
              });

        }

        private void ExecuteRemoveRemarkCommand(object obj)
        {
            Dictionary<MindNode, string> infos = SelectedItems.OfType<MindNode>().ToDictionary(p => p, p => p.Remark);

            DoCommandManager.DoNewCommand(this.ToString(),
              () => {
                  SelectedItems.OfType<MindNode>().ToList().ForEach(p => {
                      p.Remark = null;
                  });
              },
              () => {
                  foreach (var info in infos)
                  {
                      info.Key.Remark = info.Value;
                  }
              });
        }

        private void ExecuteAddPriorityCommand(object obj)
        {
            Dictionary<MindNode, double?> infos = SelectedItems.OfType<MindNode>().ToDictionary(p => p, p => p.Priority);
            DoCommandManager.DoNewCommand(this.ToString(),
              () => {
                  if (double.TryParse(obj.ToString(), out var priority))
                  {
                      SelectedItems.OfType<MindNode>().ToList().ForEach(p => p.Priority = priority);
                  }
                  else
                  {
                      SelectedItems.OfType<MindNode>().ToList().ForEach(p => p.Priority = null);
                  }
              },
              () => {
                  foreach (var info in infos)
                  {
                      info.Key.Priority = info.Value;
                  }
              });

        }

        private void ExecuteAddRatioCommand(object obj)
        {
            Dictionary<MindNode, double?> infos = SelectedItems.OfType<MindNode>().ToDictionary(p => p, p => p.Rate);
            DoCommandManager.DoNewCommand(this.ToString(),
              () => {
                  if (double.TryParse(obj.ToString(), out var rate))
                  {
                      SelectedItems.OfType<MindNode>().ToList().ForEach(p => p.Rate = rate);
                  }
                  else
                  {
                      SelectedItems.OfType<MindNode>().ToList().ForEach(p => p.Rate = null);
                  }
              },
              () => {
                  foreach (var info in infos)
                  {
                      info.Key.Rate = info.Value;
                  }
              });
        }

        private void ExecuteAddTagCommand(object obj)
        {
            DoCommandManager.DoNewCommand(this.ToString(),
              () => {
                  SelectedItems.OfType<MindNode>().ToList().ForEach(p => {
                      p.Tags.Add(obj?.ToString());
                  });
              },
              () => {
                  SelectedItems.OfType<MindNode>().ToList().ForEach(p => {
                      p.Tags.Remove(obj?.ToString());
                  });
              });

        }

        private void ExecuteRemoveTagCommand(object obj)
        {
            DoCommandManager.DoNewCommand(this.ToString(),
              () => {
                  SelectedItems.OfType<MindNode>().ToList().ForEach(p => {
                      p.Tags.Remove(obj?.ToString());
                  });
              },
              () => {
                  SelectedItems.OfType<MindNode>().ToList().ForEach(p => {
                      p.Tags.Add(obj?.ToString());
                  });
              });

        }
        #endregion

        #region 改变模式，主题
        private void ChangeMindType(MindType oldMindType, MindType newMindType)
        {
            List<MindNode> roots;
            if (RootItems.Count == 1)//只有一个的时候
            {
                roots = RootItems.ToList();
            }
            else
            {
                roots = MindSelectedItems.Select(p => p.RootNode).Distinct().ToList();
            }

            if (roots.Count > 0)
            {
                DoCommandManager.DoNewCommand(this.ToString(),
               () => {
                   roots.ForEach(p => p.MindType = newMindType);
                   roots.SelectMany(p => p.GetChildren(true)).ToList().ForEach(item => { item.InitLayout(true); });
                   roots.SelectMany(p => p.GetChildren(true)).ToList().ForEach(item => { item.InitConnectionLayout(); });
                   roots.ForEach(p => p.UpdatedLayout());
               },
               () => {
                   roots.ForEach(p => p.MindType = oldMindType);
                   roots.SelectMany(p => p.GetChildren(true)).ToList().ForEach(item => { item.InitLayout(true); });
                   roots.SelectMany(p => p.GetChildren(true)).ToList().ForEach(item => { item.InitConnectionLayout(); });
                   roots.ForEach(p => p.UpdatedLayout());
               });
            }
        }

        private void ChangeMindTheme(MindTheme oldMindTheme, MindTheme newMindTheme)
        {
            List<MindNode> roots;
            if (RootItems.Count == 1)//只有一个的时候
            {
                roots = RootItems.ToList();
            }
            else
            {
                roots = MindSelectedItems.Select(p => p.RootNode).Distinct().ToList();
            }

            if (roots.Count > 0)
            {
                DoCommandManager.DoNewCommand(this.ToString(),
                () => {
                    var mindThemeModel = MindThemeHelper.GetTheme(newMindTheme);
                    if (mindThemeModel?.Dark == true)
                    {
                        DiagramOption.LayoutOption.PageBackground = Colors.Black;
                    }
                    else
                    {
                        DiagramOption.LayoutOption.PageBackground = Colors.White;
                    }
                    roots.ForEach(p => p.MindTheme = newMindTheme);
                    roots.SelectMany(p => p.GetChildren(true)).ToList().ForEach(item => { item.ThemeChange(); });
                    roots.ForEach(p => p.UpdatedLayout());
                },
                () => {
                    var mindThemeModel = MindThemeHelper.GetTheme(oldMindTheme);
                    if (mindThemeModel?.Dark == true)
                    {
                        DiagramOption.LayoutOption.PageBackground = Colors.Black;
                    }
                    else
                    {
                        DiagramOption.LayoutOption.PageBackground = Colors.White;
                    }
                    roots.ForEach(p => p.MindTheme = oldMindTheme);
                    roots.SelectMany(p => p.GetChildren(true)).ToList().ForEach(item => { item.ThemeChange(); });
                    roots.ForEach(p => p.UpdatedLayout());
                });
            }
        }

        private void ExecutedClearThemeCommand(object parameter)
        {
            List<MindNode> items = new List<MindNode>();
            if (parameter is MindNode node)
            {
                items.Add(node);
            }
            else if (parameter is IEnumerable<MindNode> para)
            {
                items.AddRange(para);
            }
            else
            {
                items.AddRange(SelectedItems.OfType<MindNode>());
            }

            if (items.Any())
            {
                Dictionary<MindNode, MindThemeModel> infos = items.OfType<MindNode>().ToDictionary(p => p, p => MindThemeHelper.GetNodeTheme(p));
                DoCommandManager.DoNewCommand(this.ToString(),
                  () => {
                      foreach (var item in items)
                      {
                          item.ThemeChange();
                      }
                  },
                  () => {
                      foreach (var info in infos)
                      {
                          MindThemeHelper.SetThemeModel(info.Key, info.Value);
                      }
                  });
            }
        }

        private MindNode _formatNode;
        private void ExecutedCopyThemeCommand(object parameter)
        {
            if (parameter is MindNode node)
            {

            }
            else
            {
                node = SelectedItem as MindNode;
            }

            if (node != null)
            {
                _formatNode = node;
            }
        }

        private void ExecutedPasteThemeCommand(object parameter)
        {
            if (_formatNode != null)
            {
                List<MindNode> items = new List<MindNode>();
                if (parameter is MindNode node)
                {
                    items.Add(node);
                }
                else if (parameter is IEnumerable<MindNode> para)
                {
                    items.AddRange(para);
                }
                else
                {
                    items.AddRange(SelectedItems.OfType<MindNode>());
                }

                if (items.Any())
                {
                    Dictionary<MindNode, Tuple<IColorViewModel, IFontViewModel>> infos = items.OfType<MindNode>().ToDictionary(p => p, p => new Tuple<IColorViewModel, IFontViewModel>(MindThemeHelper.GetColorViewModel(p), MindThemeHelper.GetFontViewModel(p)));
                    DoCommandManager.DoNewCommand(this.ToString(),
                      () => {
                          foreach (var item in items)
                          {
                              CopyHelper.CopyPropertyValue(_formatNode.ColorViewModel, item.ColorViewModel);
                              CopyHelper.CopyPropertyValue(_formatNode.FontViewModel, item.FontViewModel);
                          }
                      },
                      () => {
                          foreach (var info in infos)
                          {
                              CopyHelper.CopyPropertyValue(info.Value.Item1, info.Key.ColorViewModel);
                              CopyHelper.CopyPropertyValue(info.Value.Item2, info.Key.FontViewModel);
                          }
                      });
                }
            }
        }
        #endregion

        #region 操作
        protected override void ExecuteCenterMoveCommand(object parameter)
        {
            var rootitem = MindSelectedItem?.RootNode;
            if (rootitem != null)
            {
                var left = rootitem.Left;
                var top = rootitem.Top;
                DoCommandManager.DoNewCommand(this.ToString(),
                      () => {
                          Move(rootitem, null, null);
                      },
                      () => {
                          Move(rootitem, left, top);
                      });
            }
        }

        private void Move(MindNode rootitem, double? left, double? top)
        {

            if (left == null)
                left = (DiagramOption.LayoutOption.PageSize.Width - rootitem.ItemWidth) / 2;
            if (top == null)
                top = (DiagramOption.LayoutOption.PageSize.Height - rootitem.ItemHeight) / 2;
            var offset = rootitem.Offset;
            rootitem.Left = left.Value;
            rootitem.Top = top.Value;
            rootitem.Offset = offset;
            rootitem?.UpdatedLayout();
            FitViewModel = new FitViewModel() { BoundingRect = rootitem.GetBounds() };
        }

        private void ExecutedExpand2LevelCommand(object obj)
        {
            int level = 0;
            if (int.TryParse(obj?.ToString(), out level))
            {
                Dictionary<MindNode, bool> infos = Items.OfType<MindNode>().ToDictionary(p => p, p => p.IsExpanded);
                DoCommandManager.DoNewCommand(this.ToString(),
                () => {
                    foreach (var item in Items.OfType<MindNode>())
                    {
                        if (item.NodeLevel == 0)
                        {
                            continue;
                        }
                        else if (item.NodeLevel < level)
                        {
                            item.IsExpanded = true;
                        }
                        else
                        {
                            item.IsExpanded = false;
                        }
                    }
                },
                () => {
                    foreach (var info in infos)
                    {
                        info.Key.IsExpanded = info.Value;
                    }
                });
            }
        }

        protected void ExecuteSelectBrotherCommand(object parameter)
        {
            List<MindNode> items = new List<MindNode>();
            if (parameter is MindNode node)
            {
                items.Add(node);
            }
            else if (parameter is IEnumerable<MindNode> para)
            {
                items.AddRange(para);
            }
            else
            {
                items.AddRange(SelectedItems.OfType<MindNode>());
            }

            if (items.Any())
            {
                List<MindNode> selecteditems = new List<MindNode>();
                DoCommandManager.DoNewCommand(this.ToString(),
                () => {
                    foreach (var item in items)
                    {
                        if (item != null && item.ParentNode != null)
                        {
                            foreach (var child in item.ParentNode.Children)
                            {
                                if (child.IsSelected != true)
                                {
                                    child.IsSelected = true;
                                    selecteditems.Add(child);
                                }
                            }
                        }
                    }
                },
                () => {
                    foreach (var item in selecteditems)
                    {
                        item.IsSelected = false;
                    }
                });
            }
        }

        protected void ExecuteSelectPearCommand(object parameter)
        {
            List<MindNode> items = new List<MindNode>();
            if (parameter is MindNode node)
            {
                items.Add(node);
            }
            else if (parameter is IEnumerable<MindNode> para)
            {
                items.AddRange(para);
            }
            else
            {
                items.AddRange(SelectedItems.OfType<MindNode>());
            }

            if (items.Any())
            {
                List<MindNode> selecteditems = new List<MindNode>();
                DoCommandManager.DoNewCommand(this.ToString(),
                () => {
                    foreach (var item in items)
                    {
                        foreach (var pear in Items.OfType<MindNode>().Where(p => p.RootNode == item.RootNode && p.NodeLevel == item.NodeLevel))
                        {
                            if (pear.IsSelected != true)
                            {
                                pear.IsSelected = true;
                                selecteditems.Add(pear);
                            }
                        }
                    }
                },
                () => {
                    foreach (var item in selecteditems)
                    {
                        item.IsSelected = false;
                    }
                });
            }
        }

        protected void ExecuteSelectRouteCommand(object parameter)
        {
            List<MindNode> items = new List<MindNode>();
            if (parameter is MindNode node)
            {
                items.Add(node);
            }
            else if (parameter is IEnumerable<MindNode> para)
            {
                items.AddRange(para);
            }
            else
            {
                items.AddRange(SelectedItems.OfType<MindNode>());
            }
            if (items.Any())
            {
                List<MindNode> selecteditems = new List<MindNode>();
                DoCommandManager.DoNewCommand(this.ToString(),
                  () => {
                      foreach (var item in items)
                      {
                          var parents = item.GetParent();
                          foreach (var parent in parents)
                          {
                              if (parent.IsSelected != true)
                              {
                                  parent.IsSelected = true;
                                  selecteditems.Add(parent);
                              }
                          }
                      }
                  }, () => {
                      foreach (var item in selecteditems)
                      {
                          item.IsSelected = false;
                      }
                  });
            }
        }

        protected void ExecuteSelectChildCommand(object parameter)
        {
            List<MindNode> items = new List<MindNode>();
            if (parameter is MindNode node)
            {
                items.Add(node);
            }
            else if (parameter is IEnumerable<MindNode> para)
            {
                items.AddRange(para);
            }
            else
            {
                items.AddRange(SelectedItems.OfType<MindNode>());
            }
            if (items.Any())
            {
                List<MindNode> selecteditems = new List<MindNode>();
                DoCommandManager.DoNewCommand(this.ToString(),
                  () => {
                      foreach (var item in items)
                      {
                          var children = item.GetChildren();
                          foreach (var child in children)
                          {
                              if (child.IsSelected != true)
                              {
                                  child.IsSelected = true;
                                  selecteditems.Add(child);
                              }
                          }
                      }
                  }, () => {
                      foreach (var item in selecteditems)
                      {
                          item.IsSelected = false;
                      }
                  });
            }
        }
        #endregion


    }
}
