using DevExpress.Xpf.Bars;
using DevExpress.Xpf.Core;
using log4net;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Forms;
using VIZ.Framework.Core;
using VIZ.Package.Domain;
using VIZ.Package.Domain.Model;
using VIZ.Package.Service;
using VIZ.Package.Storage;

namespace VIZ.Package.Module
{
    /// <summary>
    /// 主视图顶部视图模型
    /// </summary>
    public class MainTopViewModel : ViewModelBase
    {
        /// <summary>
        /// 日志
        /// </summary>
        private readonly static ILog log = LogManager.GetLogger(typeof(MainTopViewModel));

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

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

        /// <summary>
        /// 初始化命令
        /// </summary>
        private void InitCommand()
        {
            this.LoadedCommand = new VCommand(this.Loaded);

            this.CreateProjectCommand = new VCommand(this.CreateProject);
            this.OpenProjectCommand = new VCommand(this.OpenProject);
            this.SaveProjectCommand = new VCommand(this.SaveProject, this.CanSaveProject);
            this.CloseProjectCommand = new VCommand(this.CloseProject, this.CanCloseProject);

            this.SettingCommand = new VCommand(this.Setting);
            this.ResetLayoutCommand = new VCommand(this.ResetLayout);
            this.AboutCommand = new VCommand(this.About);
            this.AboutCustomControlFieldCommand = new VCommand(this.AboutCustomControlField);
        }

        /// <summary>
        /// 初始化消息
        /// </summary>
        private void InitMessage()
        {
            ApplicationDomainEx.MessageManager.Register<HotkeyMessage>(this, this.OnHotkeyMessage);
            ApplicationDomainEx.MessageManager.Register<VizPreviewReadyMessage>(this, this.OnVizPreviewReadyMessage);
            ApplicationDomainEx.MessageManager.Register<VizPreviewRestartMessage>(this, this.OnVizPreviewRestartMessage);
            ApplicationDomainEx.MessageManager.Register<ApplicationClosingMessage>(this, this.OnApplicationClosingMessage);
        }

        // =====================================================================
        // Field
        // =====================================================================

        /// <summary>
        /// 是否需要打开最后的项目，在系统启动后会尝试打开之前的项目
        /// </summary>
        private bool isNeedOpenLastProject = true;

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

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

        #region ProjectName -- 项目名

        private string projectName;
        /// <summary>
        /// 项目名
        /// </summary>
        public string ProjectName
        {
            get { return projectName; }
            set { projectName = value; this.RaisePropertyChanged(nameof(ProjectName)); }
        }

        #endregion

        #region IsVizPreviewReady -- Viz预览是否准备完毕

        private bool isVizPreviewReady;
        /// <summary>
        /// Viz预览是否准备完毕
        /// </summary>
        public bool IsVizPreviewReady
        {
            get { return isVizPreviewReady; }
            set { isVizPreviewReady = value; this.RaisePropertyChanged(nameof(IsVizPreviewReady)); }
        }

        #endregion

        #region ItemsSource -- 视图项

        private ObservableCollection<MenuItemModel> itemsSource;
        /// <summary>
        /// 视图项
        /// </summary>
        public ObservableCollection<MenuItemModel> ItemsSource
        {
            get { return itemsSource; }
            set { itemsSource = value; this.RaisePropertyChanged(nameof(ItemsSource)); }
        }

        #endregion

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

        #region LoadedCommand -- 加载命令

        /// <summary>
        /// 加载命令
        /// </summary>
        public VCommand LoadedCommand { get; set; }

        /// <summary>
        /// 加载
        /// </summary>
        private void Loaded()
        {
            if (this.IsAlreadyLoaded)
                return;

            this.IsAlreadyLoaded = true;

            List<PluginInfo> plugins = ApplicationDomainEx.PluginInfos.Where(p => (p.Group == ApplicationConstants.APPLICATION_GROUP_NAME ||
                                                                                   p.Group == ApplicationDomainEx.VizConfig.PluginGroup) &&
                                                                                   p.PluginType == PluginType.Module).ToList();

            var items = plugins.Select(p => new MenuItemModel
            {
                Data = p,
                Type = MenuItemType.CheckBox
            }).ToList();

            items.Add(new MenuItemModel { Type = MenuItemType.Separator });
            items.Add(new MenuItemModel
            {
                Header = "重置布局",
                Icon = "/VIZ.Package.Module.Resource;component/Icons/top_icon_layout_20x20.png",
                Type = MenuItemType.Button,
                Command = this.ResetLayoutCommand
            });

            this.ItemsSource = items.ToObservableCollection();
        }

        #endregion

        #region CreateProjectCommand -- 创建项目命令

        /// <summary>
        /// 创建项目命令
        /// </summary>
        public VCommand CreateProjectCommand { get; set; }

        /// <summary>
        /// 创建项目
        /// </summary>
        private void CreateProject()
        {
            // 保存之前的项目
            if (ApplicationDomainEx.ProjectDbContext != null)
            {
                var result = DXMessageBox.Show("是否保存当前项目", "提示", System.Windows.MessageBoxButton.YesNo);

                if (result == System.Windows.MessageBoxResult.Yes)
                {
                    this.SaveProject();
                }
            }

            // 创建项目文件
            SaveProjectWindow window = new SaveProjectWindow();
            window.ShowDialog();
            if (window.DialogResult != true)
                return;

            SaveProjectWindowModel vm = window.DataContext as SaveProjectWindowModel;
            if (vm == null)
                return;

            string path = System.IO.Path.Combine(vm.SelectedFolderModel.Path, vm.ProjectName);
            if (System.IO.File.Exists(path))
            {
                System.IO.File.Delete(path);
            }

            this.ProjectName = System.IO.Path.GetFileNameWithoutExtension(path);
            ApplicationDomainEx.ProjectDbContext = new ProjectDbContext(path);

            // 为项目添加默认页分组
            PageGroupEntity defaultGroup = new PageGroupEntity();
            defaultGroup.GroupID = Guid.NewGuid();
            defaultGroup.GroupName = "默认分组";
            ApplicationDomainEx.ProjectDbContext.PageGroup.Insert(defaultGroup);

            // 保存当前项目的完整路径
            ApplicationDomainEx.VizConfig.ProjectPath = path;
            ApplicationDomainEx.LocalDbContext.VizConfig.Update(ApplicationDomainEx.VizConfig);

            // 发送项目打开消息
            ProjectOpenMessage msg = new ProjectOpenMessage();
            ApplicationDomainEx.MessageManager.Send(msg);

            this.UpdateCommandStatus();

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

        #endregion

        #region OpenProjectCommand -- 打开项目命令

        /// <summary>
        /// 打开项目命令
        /// </summary>
        public VCommand OpenProjectCommand { get; set; }

        /// <summary>
        /// 打开项目
        /// </summary>
        private void OpenProject()
        {
            if (ApplicationDomainEx.ProjectDbContext != null)
            {
                var result = DXMessageBox.Show("是否保存当前项目", "提示", System.Windows.MessageBoxButton.YesNo);

                if (result == System.Windows.MessageBoxResult.Yes)
                {
                    this.SaveProject();
                }

                ApplicationDomainEx.ProjectDbContext.Dispose();
            }

            OpenProjectWindow window = new OpenProjectWindow();
            window.ShowDialog();

            if (window.DialogResult != true)
                return;

            OpenProjectWindowModel vm = window.DataContext as OpenProjectWindowModel;
            if (vm == null)
                return;

            this.OpenProject(vm.SelectedFileModel.Path);
        }

        /// <summary>
        /// 打开项目
        /// </summary>
        /// <param name="path">项目路径</param>
        private void OpenProject(string path)
        {
            // 记录操作日志
            this.recordLogService.AppendLog(ApplicationConstants.APPLICATION_GROUP_NAME, RecordLogOperate.Operate, RecordLogTrigger.Human, RecordLogConstants.OPERATE_PROJECT_OPEN, path);

            this.ProjectName = System.IO.Path.GetFileNameWithoutExtension(path);
            ApplicationDomainEx.ProjectDbContext = new ProjectDbContext(path);

            // 保存当前项目的完整路径
            ApplicationDomainEx.VizConfig.ProjectPath = path;
            ApplicationDomainEx.LocalDbContext.VizConfig.Update(ApplicationDomainEx.VizConfig);

            ProjectOpenMessage msg = new ProjectOpenMessage();
            ApplicationDomainEx.MessageManager.Send(msg);

            this.UpdateCommandStatus();
        }

        #endregion

        #region SaveProjectCommand -- 保存项目命令

        /// <summary>
        /// 保存项目命令
        /// </summary>
        public VCommand SaveProjectCommand { get; set; }

        /// <summary>
        /// 是否可以执行保存项目命令
        /// </summary>
        /// <returns>是否可以执行保存项目命令</returns>
        private bool CanSaveProject()
        {
            return ApplicationDomainEx.ProjectDbContext != null;
        }

        /// <summary>
        /// 保存项目
        /// </summary>
        private void SaveProject()
        {
            // 记录操作日志
            this.recordLogService.AppendLog(ApplicationConstants.APPLICATION_GROUP_NAME, RecordLogOperate.Operate, RecordLogTrigger.Human, RecordLogConstants.OPERATE_PROJECT_SAVE, this.ProjectName);

            ProjectSaveMessage msg = new ProjectSaveMessage();
            ApplicationDomainEx.MessageManager.Send(msg);
        }

        #endregion

        #region CloseProjectCommand -- 关闭项目命令

        /// <summary>
        /// 关闭项目命令
        /// </summary>
        public VCommand CloseProjectCommand { get; set; }

        /// <summary>
        /// 是否可以执行关闭项目
        /// </summary>
        /// <returns>是否可以执行关闭项目</returns>
        private bool CanCloseProject()
        {
            return ApplicationDomainEx.ProjectDbContext != null;
        }

        /// <summary>
        /// 关闭项目
        /// </summary>
        private void CloseProject()
        {
            if (ApplicationDomainEx.ProjectDbContext != null)
            {
                var result = DXMessageBox.Show("是否保存当前项目", "提示", System.Windows.MessageBoxButton.YesNo);

                if (result == System.Windows.MessageBoxResult.Yes)
                {
                    this.SaveProject();
                }

                ApplicationDomainEx.ProjectDbContext.Dispose();
            }

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

            this.ProjectName = null;
            ApplicationDomainEx.ProjectDbContext = null;

            // 清除当前项目的完整路径
            ApplicationDomainEx.VizConfig.ProjectPath = null;
            ApplicationDomainEx.LocalDbContext.VizConfig.Update(ApplicationDomainEx.VizConfig);

            ProjectCloseMessage msg = new ProjectCloseMessage();
            ApplicationDomainEx.MessageManager.Send(msg);

            this.UpdateCommandStatus();
        }

        #endregion

        #region SettingCommand -- 设置命令

        /// <summary>
        /// 设置命令
        /// </summary>
        public VCommand SettingCommand { get; set; }

        /// <summary>
        /// 设置
        /// </summary>
        private void Setting()
        {
            // 记录操作日志
            this.recordLogService.AppendLog(ApplicationConstants.APPLICATION_GROUP_NAME, RecordLogOperate.Operate, RecordLogTrigger.Human, RecordLogConstants.OPERATE_SETTING_OPEN);

            SettingWindow window = new SettingWindow();
            window.Owner = ApplicationDomainEx.MainWindow;
            window.ShowDialog();
        }

        #endregion

        #region ResetLayoutCommand -- 重置布局命令

        /// <summary>
        /// 重置布局命令
        /// </summary>
        public VCommand ResetLayoutCommand { get; set; }

        /// <summary>
        /// 重置布局
        /// </summary>
        private void ResetLayout()
        {
            IMainViewService service = ApplicationDomainEx.ServiceManager.GetService<IMainViewService>(ViewServiceKeys.MAIN_VIEW_SERVICE);
            if (service == null)
                return;

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

            service.LoadLayout();
        }

        #endregion

        #region AboutCommand -- 关于命令

        /// <summary>
        /// 关于命令
        /// </summary>
        public VCommand AboutCommand { get; set; }

        /// <summary>
        /// 关于
        /// </summary>
        private void About()
        {
            AboutWindow window = new AboutWindow();
            window.Owner = ApplicationDomainEx.MainWindow;
            window.ShowDialog();
        }

        #endregion

        #region AboutCustomControlFieldCommand -- 关于自定义控制字段命令

        /// <summary>
        /// 关于自定义控制字段命令
        /// </summary>
        public VCommand AboutCustomControlFieldCommand { get; set; }

        /// <summary>
        /// 关于自定义控制字段
        /// </summary>
        private void AboutCustomControlField()
        {
            AboutCustomControlFieldWindow window = new AboutCustomControlFieldWindow();
            window.Owner = ApplicationDomainEx.MainWindow;
            window.ShowDialog();
        }

        #endregion

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

        /// <summary>
        /// Viz预览准备完毕消息
        /// </summary>
        /// <param name="msg">消息</param>
        private void OnVizPreviewReadyMessage(VizPreviewReadyMessage msg)
        {
            this.IsVizPreviewReady = true;

            // 是否需要打开之前的项目
            if (!this.isNeedOpenLastProject)
                return;

            // 项目只有在启动的时候会尝试加载之前打开的项目，之后不会再尝试
            this.isNeedOpenLastProject = false;

            // 没有之前打开项目的信息 | 之前打开项目的路径已经不存在
            if (string.IsNullOrWhiteSpace(ApplicationDomainEx.VizConfig.ProjectPath) || !System.IO.File.Exists(ApplicationDomainEx.VizConfig.ProjectPath))
                return;

            // 打开项目
            this.OpenProject(ApplicationDomainEx.VizConfig.ProjectPath);
        }

        /// <summary>
        /// 预览引擎重启消息
        /// </summary>
        /// <param name="msg">消息</param>
        private void OnVizPreviewRestartMessage(VizPreviewRestartMessage msg)
        {
            this.IsVizPreviewReady = false;
        }

        /// <summary>
        /// 应用程序关闭前消息
        /// </summary>
        /// <param name="msg">消息</param>
        private void OnApplicationClosingMessage(ApplicationClosingMessage msg)
        {
            // 项目未打开
            if (ApplicationDomainEx.ProjectDbContext == null)
            {
                var result = DXMessageBox.Show("确定关闭系统?", "提示", MessageBoxButton.YesNo);

                msg.Cancel = result == MessageBoxResult.No;
            }
            // 项目已经打开
            else
            {
                var result = DXMessageBox.Show("是否保存项目?", "提示", MessageBoxButton.YesNoCancel);

                // 保存项目
                if (result == MessageBoxResult.Yes)
                {
                    this.SaveProject();

                    return;
                }

                // 取消关闭
                if (result == MessageBoxResult.Cancel)
                {
                    msg.Cancel = true;
                }
            }
        }

        /// <summary>
        /// 热键消息
        /// </summary>
        /// <param name="msg">消息</param>
        private void OnHotkeyMessage(HotkeyMessage msg)
        {
            try
            {
                if (string.Equals(msg.Key, ApplicationDomainEx.HotKeyConfig.SaveOpendPageOrTemplateAndProject))
                {
                    this.SaveProject();
                    return;
                }
            }
            catch (Exception ex)
            {
                log.Error(ex);
            }
        }

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

        /// <summary>
        /// 更新命令状态
        /// </summary>
        public void UpdateCommandStatus()
        {
            this.SaveProjectCommand.RaiseCanExecute();
            this.CloseProjectCommand.RaiseCanExecute();
        }
    }
}
