using DevExpress.Xpf.Core;
using DevExpress.Xpf.Grid;
using DevExpress.Xpf.Bars;
using log4net;
using Newtonsoft.Json.Serialization;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web.UI;
using System.Windows;
using VIZ.Framework.Core;
using VIZ.Package.Domain;
using VIZ.Package.Common;
using VIZ.Package.Service;
using VIZ.Package.Storage;
using DevExpress.Xpf.Editors.Helpers;
using System.Windows.Input;
using VIZ.Framework.Common;
using System.Windows.Controls.Primitives;

namespace VIZ.Package.Module
{
    /// <summary>
    /// 页分组视图模型
    /// </summary>
    public class PageGroupViewModel : ViewModelBase, IPageGroupService
    {
        /// <summary>
        /// 日志
        /// </summary>
        private readonly static ILog log = LogManager.GetLogger(typeof(PageGroupViewModel));

        /// <summary>
        /// 列表列信息配置文件路径
        /// </summary>
        private readonly static string PAGE_GROUP_VIEW__CSV_PATH = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "config", "GridColumnDefintion", "PageGroupView.csv");

        public PageGroupViewModel()
        {
            ApplicationDomainEx.ServiceManager.AddService(ViewServiceKeys.PAGE_GROUP_SERVICE, this);

            // 初始化列
            this.InitColumns();

            // 初始化命令
            this.InitCommand();

            // 初始化消息
            this.InitMessage();
        }

        /// <summary>
        /// 定义列信息
        /// </summary>
        private void InitColumns()
        {
            this.Columns.Add(new GridColumnDefinition { VisibleIndex = 0, ColumnKey = "Index" });
            this.Columns.Add(new GridColumnDefinition { VisibleIndex = 1, ColumnKey = "PageNum" });
            this.Columns.Add(new GridColumnDefinition { VisibleIndex = 2, ColumnKey = "ThumbnailBitmap" });
            this.Columns.Add(new GridColumnDefinition { VisibleIndex = 3, ColumnKey = "Scene" });
            this.Columns.Add(new GridColumnDefinition { VisibleIndex = 4, ColumnKey = "Remark" });
            this.Columns.Add(new GridColumnDefinition { VisibleIndex = 5, ColumnKey = "Layer" });
            this.Columns.Add(new GridColumnDefinition { VisibleIndex = 6, ColumnKey = "ConnGroupID" });
            this.Columns.Add(new GridColumnDefinition { VisibleIndex = 7, ColumnKey = "TakeInitedProgress" });
            this.Columns.Add(new GridColumnDefinition { VisibleIndex = 8, ColumnKey = "EngineType" });
            this.Columns.Add(new GridColumnDefinition { VisibleIndex = 9, ColumnKey = "PageType" });
            this.Columns.Add(new GridColumnDefinition { VisibleIndex = 10, ColumnKey = "PluginName" });

            // 根据配置文件调整列是否显示与排序
            List<GridColumnDefintionItem> items = ApplicationDomainEx.CsvDbContext.LoadColumnDefintion(PAGE_GROUP_VIEW__CSV_PATH);
            if (items == null)
                return;

            foreach (GridColumnDefintionItem item in items)
            {
                GridColumnDefinition define = this.Columns.FirstOrDefault(p => p.ColumnKey == item.ColumnKey);
                if (define == null)
                    continue;

                define.Visible = item.Visible;
                define.VisibleIndex = item.VisibleIndex;
            }
        }

        /// <summary>
        /// 初始化命令
        /// </summary>
        private void InitCommand()
        {
            this.TabAddGroupCommand = new VCommand<TabControlTabAddingEventArgs>(this.TabAddGroup);
            this.AddGroupCommand = new VCommand(this.AddGroup);
            this.RenameGroupCommand = new VCommand(this.RenameGroup);
            this.DeleteGroupCommand = new VCommand(this.DeleteGroup);
            this.CreateCmdPageCommand = new VCommand(this.CreateCmdPage, this.CanCreateCmdPage);
            this.DeleteItemCommand = new VCommand(this.DeleteItem);
            this.OpenPageCommand = new VCommand(this.OpenPage, this.CanOpenPage);
            this.OpenAndTakePageCommand = new VCommand(this.OpenAndTakePage, this.CanOpenAndTakePage);
            this.OpenAndTakeContinueCommand = new VCommand(this.OpenAndTakeContinue, this.CanOpenAndTakeContinue);
            this.OpenAndTakeOutCommand = new VCommand(this.OpenAndTakeOut, this.CanOpenAndTakeOut);
            this.UpdateCommand = new VCommand(this.Update, this.CanUpdate);
            this.TakeClearCommand = new VCommand(this.TakeClear);
            this.TakeInitCommand = new VCommand(this.TakeInit, this.CanTakeInit);
            this.TakeInitAllCommand = new VCommand(this.TakeInitAll);
            this.ColumnChoiceCommand = new VCommand(this.ColumnChoice);
            this.ShowGridMenuCommand = new VCommand<GridMenuEventArgs>(this.ShowGridMenu);
            this.CopyPageGroupCommand = new VCommand(this.CopyPageGroup, this.CanCopyPageGroup);
            this.BeginCopyPageCommand = new VCommand(this.BeginCopyPage, this.CanBeginCopyPage);
            this.PastePageCommand = new VCommand(this.PastePage, this.CanPastePage);
            this.PreviewKeyDownCommand = new VCommand<KeyEventArgs>(this.PreviewKeyDown);
        }

        /// <summary>
        /// 初始化消息
        /// </summary>
        private void InitMessage()
        {
            ApplicationDomainEx.MessageManager.Register<HotkeyMessage>(this, this.OnHotkeyMessage);
            ApplicationDomainEx.MessageManager.Register<ProjectOpenMessage>(this, this.OnProjectOpenMessage);
            ApplicationDomainEx.MessageManager.Register<ProjectCloseMessage>(this, this.OnProjectCloseMessage);
            ApplicationDomainEx.MessageManager.Register<ProjectSaveMessage>(this, this.OnProjectSaveMessage);
            ApplicationDomainEx.MessageManager.Register<ConnChangedMessage>(this, this.OnConnChangedMessage);
            ApplicationDomainEx.MessageManager.Register<ApplicationClosingMessage>(this, this.OnApplicationClosingMessage);
            ApplicationDomainEx.MessageManager.Register<PageOpenMessage>(this, this.OnPageOpenMessage);
            ApplicationDomainEx.MessageManager.Register<PageOpenOverMessage>(this, this.OnPageOpenOverMessage);

        }

        // ======================================================================================
        // Controller & Service
        // ======================================================================================

        /// <summary>
        /// 页视图模型控制器
        /// </summary>
        private PageModelController pageModelController = new PageModelController();

        /// <summary>
        /// 页模型拷贝控制器
        /// </summary>
        private PageModelCopyController pageModelCopyController = new PageModelCopyController();

        /// <summary>
        /// 页服务
        /// </summary>
        private PageService pageService = new PageService();

        /// <summary>
        /// GH服务
        /// </summary>
        private GHService ghService = new GHService();

        /// <summary>
        /// Viz命令服务
        /// </summary>
        private VizCommandService vizCommandService = new VizCommandService();

        /// <summary>
        /// 控制对象服务
        /// </summary>
        private ControlObjectService controlObjectService = new ControlObjectService();

        /// <summary>
        /// 操作日志服务
        /// </summary>
        private RecordLogService recordLogService = new RecordLogService();

        // ======================================================================================
        // Property
        // ======================================================================================

        #region Columns -- 列定义

        private ObservableCollection<GridColumnDefinition> columns = new ObservableCollection<GridColumnDefinition>();
        /// <summary>
        /// 列定义
        /// </summary>
        public ObservableCollection<GridColumnDefinition> Columns
        {
            get { return columns; }
            set { columns = value; this.RaisePropertyChanged(nameof(Columns)); }
        }

        #endregion

        #region IsColumnChooserVisible -- 是否显示列选择器

        private bool isColumnChooserVisible;
        /// <summary>
        /// 是否显示列选择器
        /// </summary>
        public bool IsColumnChooserVisible
        {
            get { return isColumnChooserVisible; }
            set { isColumnChooserVisible = value; this.RaisePropertyChanged(nameof(IsColumnChooserVisible)); }
        }

        #endregion

        #region IsEnabled -- 是否可用

        private bool isEnabled;
        /// <summary>
        /// 是否可用
        /// </summary>
        public bool IsEnabled
        {
            get { return isEnabled; }
            set { isEnabled = value; this.RaisePropertyChanged(nameof(IsEnabled)); }
        }

        #endregion

        #region IsLoading -- 是否正在加载

        private bool isLoading;
        /// <summary>
        /// 是否正在加载
        /// </summary>
        public bool IsLoading
        {
            get { return isLoading; }
            set { isLoading = value; this.RaisePropertyChanged(nameof(IsLoading)); }
        }

        #endregion

        #region IsWaitingPageOpen -- 是否正在等待页打开

        private bool isWaitingPageOpen;
        /// <summary>
        /// 是否正在等待页打开
        /// </summary>
        public bool IsWaitingPageOpen
        {
            get { return isWaitingPageOpen; }
            set { isWaitingPageOpen = value; this.RaisePropertyChanged(nameof(IsWaitingPageOpen)); }
        }

        #endregion

        #region PageGroupModels -- 页分组集合

        private ObservableCollection<PageGroupModel> pageGroupModels;
        /// <summary>
        /// 页分组集合
        /// </summary>
        public ObservableCollection<PageGroupModel> PageGroupModels
        {
            get { return pageGroupModels; }
            set { pageGroupModels = value; this.RaisePropertyChanged(nameof(PageGroupModels)); }
        }

        #endregion

        #region SelectedPageGroupModel -- 当前选中的页分组

        private PageGroupModel selectedPageGroupModel;
        /// <summary>
        /// 当前选中的页分组
        /// </summary>
        public PageGroupModel SelectedPageGroupModel
        {
            get { return selectedPageGroupModel; }
            set { selectedPageGroupModel = value; this.RaisePropertyChanged(nameof(SelectedPageGroupModel)); }
        }

        #endregion

        #region ConnGroups -- 连接分组集合

        private ObservableCollection<ConnGroupModel> connGroups;
        /// <summary>
        /// 连接分组集合
        /// </summary>
        public ObservableCollection<ConnGroupModel> ConnGroups
        {
            get { return connGroups; }
            set { connGroups = value; this.RaisePropertyChanged(nameof(ConnGroups)); }
        }

        #endregion

        // ======================================================================================
        // Command
        // ======================================================================================

        #region TabAddGroupCommand -- 页签添加分组命令

        /// <summary>
        /// 添加节目单命令
        /// </summary>
        public VCommand<TabControlTabAddingEventArgs> TabAddGroupCommand { get; set; }

        /// <summary>
        /// 添加节目单
        /// </summary>
        private void TabAddGroup(TabControlTabAddingEventArgs e)
        {
            PageGroupModel model = new PageGroupModel();
            model.GroupID = Guid.NewGuid();
            model.GroupName = "新建分组";

            e.Item = model;

            // 记录操作日志
            this.recordLogService.AppendLog(ApplicationConstants.APPLICATION_GROUP_NAME, RecordLogOperate.Operate, RecordLogTrigger.Human, RecordLogConstants.OPERATE_PAGE_GROUP_ADD, model.GroupName);
        }

        #endregion

        #region AddGroupCommand -- 添加分组命令

        /// <summary>
        /// 添加分组命令
        /// </summary>
        public VCommand AddGroupCommand { get; set; }

        /// <summary>
        /// 添加分组
        /// </summary>
        private void AddGroup()
        {
            PageGroupModel model = new PageGroupModel();
            model.GroupID = Guid.NewGuid();
            model.GroupName = "新建分组";

            this.PageGroupModels.Add(model);

            // 记录操作日志
            this.recordLogService.AppendLog(ApplicationConstants.APPLICATION_GROUP_NAME, RecordLogOperate.Operate, RecordLogTrigger.Human, RecordLogConstants.OPERATE_PAGE_GROUP_ADD, model.GroupName);
        }

        #endregion

        #region RenameGroup -- 重命名分组命令

        /// <summary>
        /// 重命名分组命令
        /// </summary>
        public VCommand RenameGroupCommand { get; set; }

        /// <summary>
        /// 重命名分组
        /// </summary>
        private void RenameGroup()
        {
            PageGroupRenameWindow window = new PageGroupRenameWindow();
            PageGroupRenameViewModel vm = window.DataContext as PageGroupRenameViewModel;
            vm.PageGroupName = this.SelectedPageGroupModel.GroupName?.Trim() ?? string.Empty;
            if (window.ShowDialog() != true)
                return;

            // 记录操作日志
            string remark = $"{this.SelectedPageGroupModel.GroupName} -> {vm.PageGroupName}";
            this.recordLogService.AppendLog(ApplicationConstants.APPLICATION_GROUP_NAME, RecordLogOperate.Operate, RecordLogTrigger.Human, RecordLogConstants.OPERATE_PAGE_GROUP_RENAME, remark);

            this.SelectedPageGroupModel.GroupName = vm.PageGroupName;
        }

        #endregion

        #region DeleteGroupCommand -- 删除分组命令

        /// <summary>
        /// 删除分组命令
        /// </summary>
        public VCommand DeleteGroupCommand { get; set; }

        /// <summary>
        /// 删除分组
        /// </summary>
        private void DeleteGroup()
        {
            if (this.SelectedPageGroupModel == null)
                return;

            if (DXMessageBox.Show($"是否删除分组【{this.SelectedPageGroupModel.GroupName}】?", "提示", MessageBoxButton.YesNo) != MessageBoxResult.Yes)
                return;

            // 记录操作日志
            string remark = $"{this.SelectedPageGroupModel.GroupName}";
            this.recordLogService.AppendLog(ApplicationConstants.APPLICATION_GROUP_NAME, RecordLogOperate.Operate, RecordLogTrigger.Human, RecordLogConstants.OPERATE_PAGE_GROUP_DELETE, remark);

            PageGroupModel group = this.SelectedPageGroupModel;
            this.PageGroupModels.Remove(this.SelectedPageGroupModel);

            PageGroupDeleteMessage msg = new PageGroupDeleteMessage();
            msg.PageGroup = group;
            ApplicationDomainEx.MessageManager.Send(msg);
        }

        #endregion

        #region CreateCmdPageCommand -- 创建命令模板页命令

        /// <summary>
        /// 创建命令模板页命令
        /// </summary>
        public VCommand CreateCmdPageCommand { get; set; }

        /// <summary>
        /// 是否可以创建命令模板页
        /// </summary>
        /// <returns>是否可以添加模板页</returns>
        private bool CanCreateCmdPage()
        {
            return this.SelectedPageGroupModel != null;
        }

        /// <summary>
        /// 创建命令模板页
        /// </summary>
        private void CreateCmdPage()
        {
            this.AddCmdPage();
        }

        #endregion

        #region DeleteItemCommand -- 刪除項命令

        /// <summary>
        /// 删除项命令
        /// </summary>
        public VCommand DeleteItemCommand { get; set; }

        /// <summary>
        /// 删除项
        /// </summary>
        private void DeleteItem()
        {
            if (this.SelectedPageGroupModel == null)
                return;

            if (this.SelectedPageGroupModel.SelectedPages == null || this.SelectedPageGroupModel.SelectedPages.Count == 0)
                return;

            string pageNums = string.Join(" ,", this.SelectedPageGroupModel.SelectedPages.Select(p => p.GetPageNumString()));
            if (DXMessageBox.Show($"是否删除页 [{pageNums}] ?", "提示", MessageBoxButton.YesNo) != MessageBoxResult.Yes)
                return;

            List<PageModel> pages = this.SelectedPageGroupModel.SelectedPages.ToList();

            // 记录操作日志
            string remark = string.Join("", pages.Select(p => p.Scene));
            this.recordLogService.AppendLog(ApplicationConstants.APPLICATION_GROUP_NAME, RecordLogOperate.Operate, RecordLogTrigger.Human, RecordLogConstants.OPERATE_PAGE_DELETE, remark);

            foreach (PageModel page in pages)
            {
                this.SelectedPageGroupModel.Pages.Remove(page);
            }

            PageDeleteMessage msg = new PageDeleteMessage();
            msg.Pages = pages.ToList<PageModelBase>();
            ApplicationDomainEx.MessageManager.Send(msg);
        }

        #endregion

        #region OpenPageCommand -- 打开页命令

        /// <summary>
        /// 打开场景页命令
        /// </summary>
        public VCommand OpenPageCommand { get; set; }

        /// <summary>
        /// 是否可以打开页
        /// </summary>
        /// <returns>是否可以打开页</returns>
        private bool CanOpenPage()
        {
            return this.SelectedPageGroupModel != null &&
                   this.SelectedPageGroupModel.SelectedPage != null;
        }

        /// <summary>
        /// 打开页
        /// </summary>
        private void OpenPage()
        {
            if (this.SelectedPageGroupModel == null)
                return;

            if (this.SelectedPageGroupModel.SelectedPage == null)
                return;

            // 记录操作日志
            string remark = $"{this.SelectedPageGroupModel.SelectedPage.ScenePath}";
            this.recordLogService.AppendLog(ApplicationConstants.APPLICATION_GROUP_NAME, RecordLogOperate.Operate, RecordLogTrigger.Human, RecordLogConstants.OPERATE_PAGE_OPEN, remark);

            this.OpenPage(this.SelectedPageGroupModel.SelectedPage);
        }

        #endregion

        #region OpenAndTakePageCommand -- 打开并Take页命令

        /// <summary>
        /// 打开并Take页命令
        /// </summary>
        public VCommand OpenAndTakePageCommand { get; set; }

        /// <summary>
        /// 是否可以打开并Take页
        /// </summary>
        /// <returns>是否可以打开并Take页</returns>
        private bool CanOpenAndTakePage()
        {
            return this.SelectedPageGroupModel != null &&
                   this.SelectedPageGroupModel.SelectedPage != null;
        }

        /// <summary>
        /// 打开并Take页
        /// </summary>
        private void OpenAndTakePage()
        {
            if (this.SelectedPageGroupModel == null)
                return;

            if (this.SelectedPageGroupModel.SelectedPage == null)
                return;

            // 记录操作日志
            string remark = $"{this.SelectedPageGroupModel.SelectedPage.ScenePath}";
            this.recordLogService.AppendLog(ApplicationConstants.APPLICATION_GROUP_NAME, RecordLogOperate.Operate, RecordLogTrigger.Human, RecordLogConstants.OPERATE_PAGE_OPEN, remark);

            // 设置需要等待Take的页
            IControlService service = ApplicationDomainEx.ServiceManager.GetService<IControlService>(ViewServiceKeys.CONTROL_SERVICE);
            if (service == null)
                return;

            service.TakeWhenPageOpend(this.SelectedPageGroupModel.SelectedPage);

            // 打开页
            this.OpenPage(this.SelectedPageGroupModel.SelectedPage);
        }

        #endregion

        #region OpenAndTakeContinueCommand -- 打开并Continue页命令

        /// <summary>
        /// 打开并Continue页命令
        /// </summary>
        public VCommand OpenAndTakeContinueCommand { get; set; }

        /// <summary>
        /// 是否可以打开并Continue页
        /// </summary>
        /// <returns>是否可以打开并Continue页</returns>
        private bool CanOpenAndTakeContinue()
        {
            return this.SelectedPageGroupModel != null && this.SelectedPageGroupModel.SelectedPage != null && this.SelectedPageGroupModel.SelectedPage.IsTake;
        }

        /// <summary>
        /// 打开并Continue页
        /// </summary>
        private void OpenAndTakeContinue()
        {
            if (this.SelectedPageGroupModel == null)
                return;

            if (this.SelectedPageGroupModel.SelectedPage == null)
                return;

            // 记录操作日志
            string remark = $"{this.SelectedPageGroupModel.SelectedPage.ScenePath}";
            this.recordLogService.AppendLog(ApplicationConstants.APPLICATION_GROUP_NAME, RecordLogOperate.Operate, RecordLogTrigger.Human, RecordLogConstants.OPERATE_PAGE_OPEN, remark);

            // 设置需要等待Continue的页
            IControlService service = ApplicationDomainEx.ServiceManager.GetService<IControlService>(ViewServiceKeys.CONTROL_SERVICE);
            if (service == null)
                return;

            service.TakeContinueWhenPageOpend(this.SelectedPageGroupModel.SelectedPage);

            // 打开页
            this.OpenPage(this.SelectedPageGroupModel.SelectedPage);
        }

        #endregion

        #region OpenAndTakeOutCommand -- 打开并下板命令

        /// <summary>
        /// 打开并下板命令
        /// </summary>
        public VCommand OpenAndTakeOutCommand { get; set; }

        /// <summary>
        /// 是否可以执行打开并下板命令
        /// </summary>
        /// <returns>是否可以执行下板</returns>
        private bool CanOpenAndTakeOut()
        {
            return this.SelectedPageGroupModel != null && this.SelectedPageGroupModel.SelectedPage != null && this.SelectedPageGroupModel.SelectedPage.IsTake;
        }

        /// <summary>
        /// 打开并下板
        /// </summary>
        private void OpenAndTakeOut()
        {
            if (this.SelectedPageGroupModel == null)
                return;

            if (this.SelectedPageGroupModel.SelectedPage == null)
                return;

            // 记录操作日志
            string remark = $"{this.SelectedPageGroupModel.SelectedPage.ScenePath}";
            this.recordLogService.AppendLog(ApplicationConstants.APPLICATION_GROUP_NAME, RecordLogOperate.Operate, RecordLogTrigger.Human, RecordLogConstants.OPERATE_PAGE_OPEN, remark);

            // 设置需要等待Continue的页
            IControlService service = ApplicationDomainEx.ServiceManager.GetService<IControlService>(ViewServiceKeys.CONTROL_SERVICE);
            if (service == null)
                return;

            service.TakeOutWhenPageOpend(this.SelectedPageGroupModel.SelectedPage);

            // 打开页
            this.OpenPage(this.SelectedPageGroupModel.SelectedPage);
        }

        #endregion

        #region UpdateCommand -- 更新命令

        /// <summary>
        /// 更新命令
        /// </summary>
        public VCommand UpdateCommand { get; set; }

        /// <summary>
        /// 是否可以更新页
        /// </summary>
        /// <returns></returns>
        private bool CanUpdate()
        {
            return this.SelectedPageGroupModel != null &&
                   this.SelectedPageGroupModel.SelectedPages != null &&
                   this.SelectedPageGroupModel.SelectedPages.Count > 0;
        }

        /// <summary>
        /// 更新
        /// </summary>
        private void Update()
        {
            if (this.SelectedPageGroupModel == null)
                return;

            if (this.SelectedPageGroupModel.SelectedPages == null || this.SelectedPageGroupModel.SelectedPages.Count == 0)
                return;

            List<PageModelBase> pages = this.SelectedPageGroupModel.SelectedPages.ToList<PageModelBase>();

            // 记录操作日志
            string remark = string.Join(",", pages.Select(p => p.Scene));
            this.recordLogService.AppendLog(ApplicationConstants.APPLICATION_GROUP_NAME, RecordLogOperate.Operate, RecordLogTrigger.Human, RecordLogConstants.OPERATE_PAGE_UPDATE, remark);

            // 开始下载控制对象
            this.pageModelController.BeginDownLoadControlObject(pages, () =>
            {
                // 控制对象下载完成后打开最后一个模板
                PageModel last = pages.LastOrDefault() as PageModel;
                if (last == null)
                    return;

                this.OpenPage(last);
            });
        }

        #endregion

        #region TakeClearCommand -- 页清理命令

        /// <summary>
        /// 页清理命令
        /// </summary>
        public VCommand TakeClearCommand { get; set; }

        /// <summary>
        /// 页清理
        /// </summary>
        private void TakeClear()
        {
            // 记录操作日志
            this.recordLogService.AppendLog(ApplicationConstants.APPLICATION_GROUP_NAME, RecordLogOperate.Operate, RecordLogTrigger.Human, RecordLogConstants.OPERATE_PAGE_CLEAR);

            // 清理状态
            lock (ApplicationDomainEx.SceneInfoList)
            {
                foreach (SceneInfoModel sceneInfo in ApplicationDomainEx.SceneInfoList)
                {
                    sceneInfo.TakeInitedProgress = 0d;
                    sceneInfo.TakeInitedMessage = null;
                }
            }
            lock (ApplicationDomainEx.SceneInfoListWithTransitionLogic)
            {
                foreach (TransitionLogicSceneInfoModel sceneInfo in ApplicationDomainEx.SceneInfoListWithTransitionLogic)
                {
                    sceneInfo.TakeInitedProgress = 0d;
                    sceneInfo.TakeInitedMessage = null;
                    sceneInfo.Connection = null;
                    sceneInfo.TransitionLogic.LayerInfos.Clear();
                }
            }

            // 开始清理
            List<ConnGroupModel> groups = ApplicationDomainEx.ConnGroups.ToList();
            this.pageModelController.BeginTakeClear(groups);

            // 清理Take状态
            if (ApplicationDomainEx.CurrentTake != null)
            {
                ApplicationDomainEx.CurrentTake.IsTake = false;
                ApplicationDomainEx.CurrentTake = null;
            }
        }

        #endregion

        #region TakeInitCommand -- 初始化页命令

        /// <summary>
        /// 初始化页命令
        /// </summary>
        public VCommand TakeInitCommand { get; set; }

        /// <summary>
        /// 是否可以初始化页
        /// </summary>
        /// <returns></returns>
        private bool CanTakeInit()
        {
            return this.SelectedPageGroupModel != null &&
                   this.SelectedPageGroupModel.SelectedPages != null &&
                   this.SelectedPageGroupModel.SelectedPages.Count > 0;
        }

        /// <summary>
        /// 初始化页
        /// </summary>
        private void TakeInit()
        {
            if (this.SelectedPageGroupModel == null)
                return;

            if (this.SelectedPageGroupModel.SelectedPages == null || this.SelectedPageGroupModel.SelectedPages.Count == 0)
                return;

            List<PageModel> pages = this.SelectedPageGroupModel.SelectedPages.ToList();

            // 记录操作日志
            string remark = string.Join(",", pages.Select(p => p.Scene));
            this.recordLogService.AppendLog(ApplicationConstants.APPLICATION_GROUP_NAME, RecordLogOperate.Operate, RecordLogTrigger.Human, RecordLogConstants.OPERATE_PAGE_INIT, remark);

            // 开始初始化
            this.pageModelController.BeginTakeInit(pages);
        }

        #endregion

        #region TakeInitAllCommand -- 初始化全部命令

        /// <summary>
        /// 初始化全部命令
        /// </summary>
        public VCommand TakeInitAllCommand { get; set; }

        /// <summary>
        /// 初始化全部
        /// </summary>
        private void TakeInitAll()
        {
            if (this.SelectedPageGroupModel == null)
                return;

            if (this.SelectedPageGroupModel.Pages == null || this.SelectedPageGroupModel.Pages.Count == 0)
                return;

            List<PageModel> pages = this.SelectedPageGroupModel.Pages.ToList();

            // 记录操作日志
            string remark = string.Join(",", pages.Select(p => p.Scene));
            this.recordLogService.AppendLog(ApplicationConstants.APPLICATION_GROUP_NAME, RecordLogOperate.Operate, RecordLogTrigger.Human, RecordLogConstants.OPERATE_PAGE_INIT, remark);

            // 开始初始化
            this.pageModelController.BeginTakeInit(pages);
        }

        #endregion

        #region ColumnChoiceCommand -- 列选择命令

        /// <summary>
        /// 列选择命令
        /// </summary>
        public VCommand ColumnChoiceCommand { get; set; }

        /// <summary>
        /// 列选择
        /// </summary>
        private void ColumnChoice()
        {
            this.IsColumnChooserVisible = true;
        }

        #endregion

        #region ShowGridMenuCommand -- 显示列命令

        /// <summary>
        /// 显示列命令
        /// </summary>
        public VCommand<GridMenuEventArgs> ShowGridMenuCommand { get; set; }

        /// <summary>
        /// 显示列
        /// </summary>
        /// <param name="e">事件参数</param>
        private void ShowGridMenu(GridMenuEventArgs e)
        {
            GridControlHelper.RemoveAllDefaultMenuItem(e);
        }

        #endregion

        #region CopyPageGroupCommand -- 拷贝页分组命令

        /// <summary>
        /// 拷贝页分组命令
        /// </summary>
        public VCommand CopyPageGroupCommand { get; set; }

        /// <summary>
        /// 是否可以拷贝页分组
        /// </summary>
        /// <returns></returns>
        private bool CanCopyPageGroup()
        {
            return this.SelectedPageGroupModel != null;
        }

        /// <summary>
        /// 拷贝页分组
        /// </summary>
        private void CopyPageGroup()
        {
            if (this.SelectedPageGroupModel == null)
                return;

            PageGroupModel destGroup = this.pageModelCopyController.CopyGroup(this.SelectedPageGroupModel);
            if (destGroup == null)
                return;

            // 记录操作日志
            string remark = $"{this.SelectedPageGroupModel.GroupName}";
            this.recordLogService.AppendLog(ApplicationConstants.APPLICATION_GROUP_NAME, RecordLogOperate.Operate, RecordLogTrigger.Human, RecordLogConstants.OPERATE_PAGE_GROUP_COPY, remark);

            destGroup.Order = this.PageGroupModels.MaxOrDefault(p => p.Order) + 1;
            this.PageGroupModels.Add(destGroup);
        }

        #endregion

        #region BeginCopyPageCommand -- 开始拷贝页命令

        /// <summary>
        /// 拷贝页命令
        /// </summary>
        /// <remarks>
        /// 指右键拷贝页
        /// </remarks>
        public VCommand BeginCopyPageCommand { get; set; }

        /// <summary>
        /// 是否可以执行开始拷贝
        /// </summary>
        /// <returns>是否可以执行开始拷贝</returns>
        private bool CanBeginCopyPage()
        {
            return this.SelectedPageGroupModel != null &&
                   this.SelectedPageGroupModel.Pages != null &&
                   this.SelectedPageGroupModel.Pages.Count > 0;
        }

        /// <summary>
        /// 拷贝页
        /// </summary>
        private void BeginCopyPage()
        {
            if (this.SelectedPageGroupModel == null ||
                this.SelectedPageGroupModel.SelectedPages == null ||
                this.SelectedPageGroupModel.SelectedPages.Count == 0)
            {
                this.pageModelCopyController.WaitCopyPages = null;

                return;
            }

            this.pageModelCopyController.WaitCopyPages = this.SelectedPageGroupModel.SelectedPages.ToList();

            // 记录操作日志
            string remark = string.Join(",", this.pageModelCopyController.WaitCopyPages.Select(p => p.Scene));
            this.recordLogService.AppendLog(ApplicationConstants.APPLICATION_GROUP_NAME, RecordLogOperate.Operate, RecordLogTrigger.Human, RecordLogConstants.OPERATE_PAGE_BEGIN_COPY, remark);
        }

        #endregion

        #region PastePageCommand -- 粘贴页命令

        /// <summary>
        /// 粘贴页命令
        /// </summary>
        public VCommand PastePageCommand { get; set; }

        /// <summary>
        /// 是否可以执行拷贝
        /// </summary>
        /// <returns>是否可以执行拷贝</returns>
        private bool CanPastePage()
        {
            return this.SelectedPageGroupModel != null &&
                   this.pageModelCopyController.WaitCopyPages != null &&
                   this.pageModelCopyController.WaitCopyPages.Count > 0;
        }

        /// <summary>
        /// 粘贴页命令
        /// </summary>
        private void PastePage()
        {
            if (this.SelectedPageGroupModel == null)
                return;

            if (this.pageModelCopyController.WaitCopyPages == null || this.pageModelCopyController.WaitCopyPages.Count == 0)
                return;

            // 记录操作日志
            string remark = string.Join(",", this.pageModelCopyController.WaitCopyPages.Select(p => p.Scene));
            remark = $"分组： {this.SelectedPageGroupModel.GroupName}, 页: {remark}";
            this.recordLogService.AppendLog(ApplicationConstants.APPLICATION_GROUP_NAME, RecordLogOperate.Operate, RecordLogTrigger.Human, RecordLogConstants.OPERATE_PAGE_PASTE, remark);

            int maxPageNum = this.SelectedPageGroupModel.Pages.MaxOrDefault(p => p.PageNum);
            int maxOrder = this.SelectedPageGroupModel.Pages.MaxOrDefault(p => p.Order);

            foreach (PageModel srcPage in this.pageModelCopyController.WaitCopyPages)
            {
                PageModel destPage = this.pageModelCopyController.CopyPage(srcPage);
                // 分组
                destPage.PageGroupID = this.SelectedPageGroupModel.GroupID;
                destPage.PageNum = ++maxPageNum;
                destPage.Order = ++maxOrder;

                this.SelectedPageGroupModel.Pages.Add(destPage);
            }
        }

        #endregion

        #region PreviewKeyDownCommand -- 按键按下命令

        /// <summary>
        /// 按键按下命令
        /// </summary>
        public VCommand<KeyEventArgs> PreviewKeyDownCommand { get; set; }

        /// <summary>
        /// 按键按下
        /// </summary>
        /// <param name="e">事件参数</param>
        private void PreviewKeyDown(KeyEventArgs e)
        {
            try
            {
                TextBoxBase tb = e.OriginalSource as TextBoxBase;
                if (tb != null)
                    return;

                string key = HotkeyHelper.GetHotkey(e);

                // 复制页
                if (string.Equals(key, HotKeyConfigEntity.COPY))
                {
                    // 记录操作日志
                    this.recordLogService.AppendLog(ApplicationConstants.APPLICATION_GROUP_NAME, RecordLogOperate.Operate, RecordLogTrigger.Human, RecordLogConstants.SYSTEM_HOT_KEY, key);

                    this.BeginCopyPage();
                    return;
                }

                // 粘贴页
                if (string.Equals(key, HotKeyConfigEntity.PASTE))
                {
                    // 记录操作日志
                    this.recordLogService.AppendLog(ApplicationConstants.APPLICATION_GROUP_NAME, RecordLogOperate.Operate, RecordLogTrigger.Human, RecordLogConstants.SYSTEM_HOT_KEY, key);

                    this.PastePage();
                    return;
                }

                // 删除页
                if (string.Equals(key, HotKeyConfigEntity.DELETE))
                {
                    // 记录操作日志
                    this.recordLogService.AppendLog(ApplicationConstants.APPLICATION_GROUP_NAME, RecordLogOperate.Operate, RecordLogTrigger.Human, RecordLogConstants.SYSTEM_HOT_KEY, key);

                    this.DeleteItem();
                    return;
                }
            }
            catch (Exception ex)
            {
                log.Error(ex);
            }
        }

        #endregion

        // ======================================================================================
        // Message
        // ======================================================================================

        /// <summary>
        /// 项目打开消息
        /// </summary>
        /// <param name="msg">消息</param>
        private void OnProjectOpenMessage(ProjectOpenMessage msg)
        {
            this.IsEnabled = true;
            this.PageGroupModels = null;
            this.SelectedPageGroupModel = null;
            this.IsLoading = true;
            this.UpdateConnGroups();

            ThreadHelper.SafeRun(() =>
            {
                // 页分组
                var pageGroups = this.pageService.LoadPageGroups().ToObservableCollection();

                // 更新界面
                WPFHelper.Invoke(() =>
                {
                    this.PageGroupModels = pageGroups;
                    this.SelectedPageGroupModel = pageGroups.FirstOrDefault();

                    this.IsLoading = false;
                });

                // 获取场景模板缩略图
                List<PageModelBase> pages = new List<PageModelBase>();
                foreach (PageGroupModel group in pageGroups)
                {
                    if (group.Pages == null || group.Pages.Count == 0)
                        continue;

                    pages.AddRange(group.Pages);
                }
            });
        }

        /// <summary>
        /// 项目关闭消息
        /// </summary>
        /// <param name="msg">消息</param>
        private void OnProjectCloseMessage(ProjectCloseMessage msg)
        {
            this.IsEnabled = false;
            this.IsLoading = false;
            this.PageGroupModels = null;
            this.SelectedPageGroupModel = null;
        }

        /// <summary>
        /// 项目保存消息
        /// </summary>
        /// <param name="msg">消息</param>
        private void OnProjectSaveMessage(ProjectSaveMessage msg)
        {
            this.pageService.SavePageGroups(this.PageGroupModels);
        }

        /// <summary>
        /// 连接切换消息
        /// </summary>
        /// <param name="msg">消息</param>
        private void OnConnChangedMessage(ConnChangedMessage msg)
        {
            this.UpdateConnGroups();
        }

        /// <summary>
        /// 应用程序关闭消息
        /// </summary>
        /// <param name="msg">消息</param>
        private void OnApplicationClosingMessage(ApplicationClosingMessage msg)
        {
            try
            {
                List<GridColumnDefintionItem> items = new List<GridColumnDefintionItem>();

                foreach (GridColumnDefinition define in this.Columns)
                {
                    GridColumnDefintionItem item = new GridColumnDefintionItem();
                    item.ColumnKey = define.ColumnKey;
                    item.Visible = define.Visible;
                    item.VisibleIndex = define.VisibleIndex;

                    items.Add(item);
                }

                ApplicationDomainEx.CsvDbContext.SaveColumnDefintion(PAGE_GROUP_VIEW__CSV_PATH, items);
            }
            catch (Exception ex)
            {
                log.Error(ex);
            }
        }

        /// <summary>
        /// 页打开消息
        /// </summary>
        /// <param name="msg"></param>
        private void OnPageOpenMessage(PageOpenMessage msg)
        {
            this.IsWaitingPageOpen = true;
        }

        /// <summary>
        /// 打开页面完成消息
        /// </summary>
        /// <param name="msg">消息</param>
        private void OnPageOpenOverMessage(PageOpenOverMessage msg)
        {
            this.IsWaitingPageOpen = false;
        }

        /// <summary>
        /// 处理热键消息
        /// </summary>
        /// <param name="msg">消息</param>
        private void OnHotkeyMessage(HotkeyMessage msg)
        {
            try
            {
                // 打开下一页
                if (string.Equals(msg.Key, ApplicationDomainEx.HotKeyConfig.OpenNextPage))
                {
                    // 记录操作日志
                    this.recordLogService.AppendLog(ApplicationConstants.APPLICATION_GROUP_NAME, RecordLogOperate.Operate, RecordLogTrigger.Human, RecordLogConstants.SYSTEM_HOT_KEY, msg.Key);

                    this.OpenNextPageItem();

                    return;
                }

                // Take当前页打开下一页
                if (string.Equals(msg.Key, ApplicationDomainEx.HotKeyConfig.TakeAndOpenNextPage))
                {
                    // 记录操作日志
                    this.recordLogService.AppendLog(ApplicationConstants.APPLICATION_GROUP_NAME, RecordLogOperate.Operate, RecordLogTrigger.Human, RecordLogConstants.SYSTEM_HOT_KEY, msg.Key);

                    if (!(ApplicationDomainEx.CurrentPage is PageModel))
                        return;

                    // Take当前页
                    IControlService service = ApplicationDomainEx.ServiceManager.GetService<IControlService>(ViewServiceKeys.CONTROL_SERVICE);
                    service.Take(callback: () =>
                    {
                        // 打开下一页
                        this.OpenNextPageItem();

                    });

                    return;
                }

                // 打开并Take选中页
                if (string.Equals(msg.Key, ApplicationDomainEx.HotKeyConfig.OpenAndTakeSelectedPage))
                {
                    // 记录操作日志
                    this.recordLogService.AppendLog(ApplicationConstants.APPLICATION_GROUP_NAME, RecordLogOperate.Operate, RecordLogTrigger.Human, RecordLogConstants.SYSTEM_HOT_KEY, msg.Key);

                    this.OpenAndTakePage();
                }
            }
            catch (Exception ex)
            {
                log.Error(ex);
            }
        }

        // ======================================================================================
        // Public Function
        // ======================================================================================

        /// <summary>
        /// 创建并添加命令模板页
        /// </summary>
        /// <returns>页</returns>
        public PageModel AddCmdPage()
        {
            if (this.SelectedPageGroupModel == null)
                return null;

            // 记录操作日志
            this.recordLogService.AppendLog(ApplicationConstants.APPLICATION_GROUP_NAME, RecordLogOperate.Operate, RecordLogTrigger.Human, RecordLogConstants.OPERATE_PAGE_ADD_CMD);

            // 根据模板拷贝页
            PageModel page = new PageModel();
            page.PageType = PageType.Command;
            page.ConnGroupID = ApplicationDomainEx.ConnGroups.FirstOrDefault(p => p.IsDefault)?.GroupID ?? Guid.Empty;
            page.PageGroupID = this.SelectedPageGroupModel.GroupID;

            // 页码
            page.PageNum = this.SelectedPageGroupModel.Pages.MaxOrDefault(p => p.PageNum) + 1;

            // 添加页
            this.SelectedPageGroupModel.Pages.Add(page);

            return page;
        }

        /// <summary>
        /// 添加页
        /// </summary>
        /// <param name="template">模板</param>
        /// <returns>页</returns>
        public PageModel AddPage(PageTemplateModel template)
        {
            if (this.SelectedPageGroupModel == null)
                return null;

            PageAddWindow window = new PageAddWindow();
            PageAddViewModel vm = window.DataContext as PageAddViewModel;
            vm.Scene = template.Scene;
            vm.Remark = template.Remark;
            vm.Layer = template.Layer;
            vm.TransitionLogic = template.TransitionLogic;
            vm.LayerIdentifier = template.LayerIdentifier;
            vm.StateIdentifier = template.StateIdentifier;
            vm.BackgroundScene = template.BackgroundScene;

            if (window.ShowDialog() != true)
                return null;

            // 记录操作日志
            string remark = $"{template.ScenePath}";
            this.recordLogService.AppendLog(ApplicationConstants.APPLICATION_GROUP_NAME, RecordLogOperate.Operate, RecordLogTrigger.Human, RecordLogConstants.OPERATE_PAGE_ADD, remark);

            // 根据模板拷贝页
            PageModel destPage = this.pageModelCopyController.CopyPage(template, vm, this.SelectedPageGroupModel);

            // 页码
            destPage.PageNum = this.SelectedPageGroupModel.Pages.MaxOrDefault(p => p.PageNum) + 1;

            // 添加页
            this.SelectedPageGroupModel.Pages.Add(destPage);

            return destPage;
        }

        /// <summary>
        /// 拷贝页
        /// </summary>
        /// <returns>页</returns>
        public PageModel CopyPage()
        {
            // 当前打开的页为页模型时可以被拷贝
            PageModel srcPage = ApplicationDomainEx.CurrentPage as PageModel;
            if (srcPage == null)
                return null;

            PageModel destPage = this.pageModelCopyController.CopyPage(srcPage);
            destPage.PageNum = this.SelectedPageGroupModel.Pages.MaxOrDefault(p => p.PageNum) + 1;

            // 添加页
            this.SelectedPageGroupModel.Pages.Add(destPage);

            return destPage;
        }

        /// <summary>
        /// 打开页
        /// </summary>
        /// <param name="page">页</param>
        public void OpenPage(PageModel page)
        {
            PageGroupModel group = this.PageGroupModels.FirstOrDefault(p => p.GroupID == page.PageGroupID);
            if (group == null)
                return;

            if (ApplicationDomainEx.CurrentPage != null)
            {
                ApplicationDomainEx.CurrentPage.IsOpen = false;
            }
            ApplicationDomainEx.CurrentPage = page;
            page.IsOpen = true;

            PageOpenMessage msg = new PageOpenMessage();
            msg.Page = page;
            ApplicationDomainEx.MessageManager.Send(msg);
        }

        /// <summary>
        /// 尝试改变页号
        /// </summary>
        /// <param name="page">页</param>
        /// <param name="pageNum">页号</param>
        /// <returns>是否成功改变</returns>
        public bool TryChangePageNum(PageModel page, int pageNum)
        {
            if (this.SelectedPageGroupModel == null)
                return false;

            PageModel same = this.SelectedPageGroupModel.Pages.FirstOrDefault(p => p != page && p.PageNum == pageNum);
            if (same == null)
            {
                // 记录操作日志
                string remark = $"分组：{this.SelectedPageGroupModel.GroupName}, 页: {page.PageNum} -> {pageNum}";
                this.recordLogService.AppendLog(ApplicationConstants.APPLICATION_GROUP_NAME, RecordLogOperate.Operate, RecordLogTrigger.Human, RecordLogConstants.OPERATE_PAGE_CHANGE_PAGE_NUM, remark);

                return true;
            }

            DXMessageBox.Show($"页 {pageNum} 已经存在!", "提示");

            return false;
        }

        /// <summary>
        /// 更新连接分组
        /// </summary>
        public void UpdateConnGroups()
        {
            this.ConnGroups = ApplicationDomainEx.ConnGroups;
        }

        /// <summary>
        /// 打开下一页
        /// </summary>
        public void OpenNextPageItem()
        {
            if (this.SelectedPageGroupModel == null)
                return;

            PageModel page = ApplicationDomainEx.CurrentPage as PageModel;
            if (page == null)
                return;

            if (this.SelectedPageGroupModel.Pages == null || this.SelectedPageGroupModel.Pages.Count == 0)
                return;

            int index = this.SelectedPageGroupModel.Pages.IndexOf(page);
            if (index < 0)
                return;

            ++index;
            if (this.SelectedPageGroupModel.Pages.Count <= index)
                return;

            this.SelectedPageGroupModel.SelectedPage = this.SelectedPageGroupModel.Pages[index];
            this.OpenPage();

            PageGroupView view = this.GetView<PageGroupView>();
            if (view == null)
                return;

            view.CurrentIsVisibleTableView?.ScrollIntoView(this.SelectedPageGroupModel.SelectedPage);
        }

        // ======================================================================================
        // Private Function
        // ======================================================================================

    }
}
