using DevExpress.Xpf.Core;
using log4net;
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.Service;
using VIZ.Package.Storage;

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

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

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

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

        /// <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.DeleteItemCommand = new VCommand(this.DeleteItem);
            this.OpenPageCommand = new VCommand(this.OpenPage);
            this.UpdateCommand = new VCommand(this.Update);
            this.TakeClearCommand = new VCommand(this.TakeClear);
            this.TakeInitCommand = new VCommand(this.TakeInit);
            this.TakeInitAllCommand = new VCommand(this.TakeInitAll);
        }

        /// <summary>
        /// 初始化消息
        /// </summary>
        private void InitMessage()
        {
            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);
        }

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

        /// <summary>
        /// 页视图模型辅助类
        /// </summary>
        private PageViewModelHelper pageViewModelHelper = new PageViewModelHelper();

        /// <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();

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

        #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 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;
        }

        #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);
        }

        #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;
            if (window.ShowDialog() != true)
                return;

            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;

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

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

        #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.Pages.Count == 0)
                return;

            if (DXMessageBox.Show($"是否删除项", "提示", MessageBoxButton.YesNo) != MessageBoxResult.Yes)
                return;

            List<PageModel> pages = new List<PageModel>();
            foreach (PageModel page in this.SelectedPageGroupModel.SelectedPages)
            {
                pages.Add(page);
            }

            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>
        private void OpenPage()
        {
            if (this.SelectedPageGroupModel == null)
                return;

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

            PageModel page = this.SelectedPageGroupModel.SelectedPages[0] as PageModel;
            this.OpenPage(page);
        }

        #endregion

        #region UpdateCommand -- 更新命令

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

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

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

            List<PageModelBase> pages = new List<PageModelBase>();
            foreach (PageModelBase page in this.SelectedPageGroupModel.SelectedPages)
            {
                pages.Add(page);
            }

            // 开始下载图片
            this.pageViewModelHelper.BeginDownLoadIamge(pages);

            // 开始下载控制对象
            this.pageViewModelHelper.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()
        {
            List<ConnGroupModel> groups = ApplicationDomainEx.ConnGroups.ToList();

            this.pageViewModelHelper.BeginTakeClear(groups);
        }

        #endregion

        #region TakeInitCommand -- 初始化页命令

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

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

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

            List<PageModel> pages = new List<PageModel>();
            foreach (PageModel page in this.SelectedPageGroupModel.SelectedPages)
            {
                pages.Add(page);
            }

            // 开始初始化
            this.pageViewModelHelper.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();

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

        #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;
                });

                if (this.SelectedPageGroupModel == null)
                    return;

                // 获取场景模板缩略图
                this.pageViewModelHelper.BeginDownLoadIamge(this.SelectedPageGroupModel.Pages.ToList<PageModelBase>());
            });
        }

        /// <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();
        }

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

        /// <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;

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

            PageModel page = new PageModel();
            page.PageID = Guid.NewGuid();
            page.PageGroupID = this.SelectedPageGroupModel.GroupID;
            page.Scene = template.Scene;
            page.ScenePath = template.ScenePath;
            page.ThumbnailUri = template.ThumbnailUri;
            page.Remark = vm.Remark;
            page.Layer = vm.Layer;
            page.EngineType = template.EngineType;
            page.PageType = template.PageType;
            page.TemplateID = template.TemplateID;
            page.ThumbnailBitmap = template.ThumbnailBitmap;
            page.PluginID = vm.SelectedTemplatePlugin?.ID;
            page.PluginName = vm.SelectedTemplatePlugin?.Name;
            page.PageNum = this.SelectedPageGroupModel.Pages.Count == 0 ? 1 : (this.SelectedPageGroupModel.Pages.Max(p => p.PageNum) + 1);

            // 关联连接分组
            ConnGroupModel conn = ApplicationDomainEx.ConnGroups?.FirstOrDefault(p => p.IsDefault);
            page.ConnGroupID = conn != null ? conn.GroupID : Guid.Empty;

            // 将模板控制对象拷贝值页控制对象
            this.controlObjectService.CopyControlObjects(template.TemplateID, page.PageID);

            // 将模板控制字段拷贝至页控制字段
            this.controlObjectService.CopyControlFields(template.TemplateID, page.PageID);

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

            // 获取缩略图
            this.pageViewModelHelper.BeginDownLoadIamge(new List<PageModelBase> { page });

            return page;
        }

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

            PageModel page = new PageModel();
            page.PageID = Guid.NewGuid();
            page.PageGroupID = srcPage.PageGroupID;
            page.Scene = srcPage.Scene;
            page.ScenePath = srcPage.ScenePath;
            page.ThumbnailUri = srcPage.ThumbnailUri;
            page.Remark = srcPage.Remark;
            page.Layer = srcPage.Layer;
            page.EngineType = srcPage.EngineType;
            page.PageType = srcPage.PageType;
            page.TemplateID = srcPage.TemplateID;
            page.ThumbnailBitmap = srcPage.ThumbnailBitmap;
            page.PluginID = srcPage.PluginID;
            page.PluginName = srcPage.PluginName;
            page.ConnGroupID = srcPage.ConnGroupID;
            page.SceneInfo = srcPage.SceneInfo;
            page.PageNum = this.SelectedPageGroupModel.Pages.Max(p => p.PageNum) + 1;

            // 将模板控制对象拷贝值页控制对象
            this.controlObjectService.CopyControlObjects(srcPage.PageID, page.PageID);

            // 将模板控制字段拷贝至页控制字段
            this.controlObjectService.CopyControlFields(srcPage.PageID, page.PageID);

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

            // 获取缩略图
            if (page.ThumbnailBitmap == null)
            {
                ThreadHelper.SafeRun(() =>
                {
                    var bmp = this.ghService.GetImage(page.ThumbnailUri);

                    WPFHelper.BeginInvoke(() =>
                    {
                        page.ThumbnailBitmap = bmp;
                    });
                });
            }

            return page;
        }

        /// <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;

            ApplicationDomainEx.CurrentPage = page;

            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)
                return true;

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

            return false;
        }

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

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

    }
}
