using DevExpress.Xpf.Core;
using LiteDB;
using log4net;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using VIZ.Framework.Common;
using VIZ.Framework.Core;
using VIZ.Package.Domain;
using VIZ.Package.Service;
using VIZ.Package.Storage;

namespace VIZ.Package.Module
{
    /// <summary>
    /// 字段编辑视图模型
    /// </summary>
    public class FieldEditViewModel : FieldEditViewModelBase, IFieldEditService
    {
        /// <summary>
        /// 日志
        /// </summary>
        private readonly static ILog log = LogManager.GetLogger(typeof(FieldEditViewModel));

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

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

            // 注册服务
            ApplicationDomainEx.ServiceManager.AddService(ViewServiceKeys.FIELD_EDIT_SERVICE, this);
        }

        /// <summary>
        /// 初始化命令
        /// </summary>
        private void InitCommand()
        {
            this.SaveCommand = new VCommand(this.Save);
            this.SaveAsCommand = new VCommand(this.SaveAs);
        }

        /// <summary>
        /// 初始化消息
        /// </summary>
        private void InitMessage()
        {
            ApplicationDomainEx.MessageManager.Register<HotkeyMessage>(this, this.OnHotkeyMessage);
            ApplicationDomainEx.MessageManager.Register<ControlFieldChangedMessage>(this, this.OnControlFieldChangedMessage);
            ApplicationDomainEx.MessageManager.Register<PageOpenMessage>(this, this.OnPageOpenMessage);
        }

        // =============================================================
        // Field & Service
        // =============================================================

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

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

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

        #region ControlObject -- 控制对象

        private ControlObjectModel controlObject;
        /// <summary>
        /// 控制对象
        /// </summary>
        public ControlObjectModel ControlObject
        {
            get { return controlObject; }
            set { controlObject = value; this.RaisePropertyChanged(nameof(ControlObject)); }
        }

        #endregion

        #region ControlField -- 控制字段

        private ControlFieldNodeModel controlField;
        /// <summary>
        /// 控制字段
        /// </summary>
        public ControlFieldNodeModel ControlField
        {
            get { return controlField; }
            set { controlField = value; this.RaisePropertyChanged(nameof(ControlField)); }
        }

        #endregion

        #region PageID -- 页ID

        private string pageID;
        /// <summary>
        /// 页ID
        /// </summary>
        public string PageID
        {
            get { return pageID; }
            set { pageID = value; this.RaisePropertyChanged(nameof(PageID)); }
        }

        #endregion

        #region Scene -- 场景

        private string scene;
        /// <summary>
        /// 场景
        /// </summary>
        public string Scene
        {
            get { return scene; }
            set { scene = value; this.RaisePropertyChanged(nameof(Scene)); }
        }

        #endregion

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

        #region SaveCommand -- 保存命令

        /// <summary>
        /// 保存命令
        /// </summary>
        public VCommand SaveCommand { get; set; }

        /// <summary>
        /// 保存
        /// </summary>
        private void Save()
        {
            // 当前没有打开的页或模板 || 当前没有打开的项目
            if (ApplicationDomainEx.CurrentPage == null || ApplicationDomainEx.ProjectDbContext == null)
                return;

            // 字段树服务不可用
            IFieldTreeService service = ApplicationDomainEx.ServiceManager.GetService<IFieldTreeService>(ViewServiceKeys.FIELD_TREE_SERVICE);
            if (service == null)
            {
                DXMessageBox.Show("保存失败！");
                return;
            }

            // 当前没有控制对象
            ControlObjectModel obj = service.GetControlObject();
            if (obj == null)
            {
                return;
            }

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

            // 更新列表值
            service.TryUpdateControlFieldListValue();

            // 保存
            this.controlObjectService.SaveControlFields(ApplicationDomainEx.CurrentPage, obj.AllFiledNodes);

            // 发送页保存消息
            PageSaveMessage saveMessage = new PageSaveMessage();
            saveMessage.Page = ApplicationDomainEx.CurrentPage;
            ApplicationDomainEx.MessageManager.Send(saveMessage);

            // 发送弹出提示
            AlertMessage alertMessage = new AlertMessage();
            alertMessage.Message = "保存成功";
            ApplicationDomainEx.MessageManager.Send(alertMessage);
        }

        #endregion

        #region SaveAsCommand -- 另存为命令

        /// <summary>
        /// 另存为命令
        /// </summary>
        public VCommand SaveAsCommand { get; set; }

        /// <summary>
        /// 另存为
        /// </summary>
        private void SaveAs()
        {
            // 当前没有打开的页或模板 || 当前没有打开的项目
            if (ApplicationDomainEx.CurrentPage == null || ApplicationDomainEx.ProjectDbContext == null)
            {
                return;
            }

            // 页分组服务不可用
            IPageGroupService pageGroupService = ApplicationDomainEx.ServiceManager.GetService<IPageGroupService>(ViewServiceKeys.PAGE_GROUP_SERVICE);
            if (pageGroupService == null)
            {
                DXMessageBox.Show("另存失败！");
                return;
            }

            // 更新列表值
            IFieldTreeService service = ApplicationDomainEx.ServiceManager.GetService<IFieldTreeService>(ViewServiceKeys.FIELD_TREE_SERVICE);
            if (service == null)
            {
                DXMessageBox.Show("另存失败！");
                return;
            }

            service.TryUpdateControlFieldListValue();
            // 获取当前打开页的控制对象
            ControlObjectModel controlObject = service.GetControlObject();
            if (controlObject == null)
            {
                DXMessageBox.Show("另存失败！");
                return;
            }
            PageModel newPage = null;

            // 另存模板
            if (ApplicationDomainEx.CurrentPage is PageTemplateModel srcTemplate)
            {
                newPage = pageGroupService.AddPage(srcTemplate);
                this.controlObjectService.SaveControlFields(newPage.PageID, controlObject.AllFiledNodes);
                pageGroupService.OpenPage(newPage);

                // 记录操作日志
                string remark = $"模板：{srcTemplate.ScenePath}";
                this.recordLogService.AppendLog(ApplicationConstants.APPLICATION_GROUP_NAME, RecordLogOperate.Operate, RecordLogTrigger.Human, RecordLogConstants.OPERATE_CONTROL_FIELD_SAVE_AS, remark);
            }
            // 另存页
            else if (ApplicationDomainEx.CurrentPage is PageModel srcPage)
            {
                newPage = pageGroupService.CopyPage();
                this.controlObjectService.SaveControlFields(newPage.PageID, controlObject.AllFiledNodes);
                pageGroupService.OpenPage(newPage);

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

            // 发送另存为消息
            PageSaveAsMessage saveAsMessage = new PageSaveAsMessage();
            saveAsMessage.Page = newPage;
            ApplicationDomainEx.MessageManager.Send(saveAsMessage);

            // 发送弹出提示
            AlertMessage alertMessage = new AlertMessage();
            alertMessage.Message = "另存成功";
            ApplicationDomainEx.MessageManager.Send(alertMessage);
        }

        #endregion

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

        /// <summary>
        /// 页打开消息
        /// </summary>
        /// <param name="msg">消息</param>
        private void OnPageOpenMessage(PageOpenMessage msg)
        {
            this.Scene = msg.Page?.Scene;
            if (msg.Page is PageModel page)
            {
                this.PageID = page.GetPageNumString();
            }
            else
            {
                this.PageID = null;
            }
        }

        /// <summary>
        /// 控制字段切换消息
        /// </summary>
        /// <param name="msg">消息</param>
        private void OnControlFieldChangedMessage(ControlFieldChangedMessage msg)
        {
            this.ControlObject = msg.ControlObject;
            this.ControlField = msg.ControlField;

            if (msg.ControlObject == null || msg.ControlField == null)
            {
                this.SelectedNavigationConfig = null;
                return;
            }

            NavigationConfig config = this.NavigationConfigs.FirstOrDefault(p => p.Key == msg.ControlField.Type.ToString());

            if (config != null && config.View != null && config.View.TryGetTarget(out object target))
            {
                FrameworkElement view = target as FrameworkElement;
                EditPanelModelBase model = view?.DataContext as EditPanelModelBase;

                if (model != null)
                {
                    try
                    {
                        model.FieldEditMode = FieldEditMode.Normal;
                        model.Update(this.ControlObject, this.ControlField);
                    }
                    catch (Exception ex)
                    {
                        log.Error(ex);
                    }
                }
            }

            this.SelectedNavigationConfig = config;
        }

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

                    // 保存
                    this.Save();

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

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

        // =============================================================
        // Protected Function
        // =============================================================

        /// <summary>
        /// 视图创建后触发
        /// </summary>
        /// <param name="config">导航配置</param>
        /// <param name="obj">视图</param>
        protected override void OnViewCreated(NavigationConfig config, object obj)
        {
            FrameworkElement view = obj as FrameworkElement;
            if (view == null)
                return;

            EditPanelModelBase model = view.DataContext as EditPanelModelBase;
            if (model == null)
                return;

            try
            {
                model.FieldEditMode = FieldEditMode.Normal;
                model.Update(this.ControlObject, this.ControlField);
            }
            catch (Exception ex)
            {
                log.Error(ex);
            }
        }
    }
}
