using log4net;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using VIZ.Framework.Core;
using VIZ.Package.Connection;
using VIZ.Package.Domain;
using VIZ.Package.Service;
using VIZ.Package.Storage;

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

        public MainConnViewModel()
        {
            // 初始化命令
            this.InitCommnad();

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

        /// <summary>
        /// 初始化命令
        /// </summary>
        private void InitCommnad()
        {
            this.ItemClickCommand = new VCommand<ConnModel>(this.ItemClick);
        }

        /// <summary>
        /// 初始化消息
        /// </summary>
        private void InitMessage()
        {
            ApplicationDomainEx.MessageManager.Register<ConnChangedMessage>(this, this.OnConnChangedMessage);
            ApplicationDomainEx.MessageManager.Register<VizPreviewReadyMessage>(this, this.OnVizPreviewReadyMessage);
            ApplicationDomainEx.MessageManager.Register<AlertMessage>(this, this.OnAlertMessage);
        }

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

        /// <summary>
        /// 连接服务
        /// </summary>
        private ConnService connService = new ConnService();

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

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

        #region ItemsSrouce -- 数据源

        private ObservableCollection<ConnGroupModel> itemsSrouce = new ObservableCollection<ConnGroupModel>();
        /// <summary>
        /// 数据源
        /// </summary>
        public ObservableCollection<ConnGroupModel> ItemsSrouce
        {
            get { return itemsSrouce; }
            set { itemsSrouce = value; this.RaisePropertyChanged(nameof(ItemsSrouce)); }
        }

        #endregion

        #region AlertMessage -- 弹出提示消息

        private string alertMessage;
        /// <summary>
        /// 弹出提示消息
        /// </summary>
        public string AlertMessage
        {
            get { return alertMessage; }
            set { alertMessage = value; this.RaisePropertyChanged(nameof(AlertMessage)); }
        }

        #endregion

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

        #region ItemClickCommand -- 项点击命令

        /// <summary>
        /// 项点击命令
        /// </summary>
        public VCommand<ConnModel> ItemClickCommand { get; set; }

        /// <summary>
        /// 项点击命令
        /// </summary>
        /// <param name="model">连接模型</param>
        private void ItemClick(ConnModel model)
        {
            model.IsLoading = true;

            ThreadHelper.SafeRun(action: () =>
            {
                if (model.IsConnected)
                {
                    // 记录操作日志
                    string remark = $"分组： {model.OwnerGroup?.Name} 连接: {model.IP}:{model.Port}";
                    this.recordLogService.AppendLog(ApplicationConstants.APPLICATION_GROUP_NAME, RecordLogOperate.Operate, RecordLogTrigger.Human, RecordLogConstants.OPERATE_SETTING_VIZ_DISCONNECTION, remark);

                    model.EndpointManager.Disconnect();
                }
                else
                {
                    // 记录操作日志
                    string remark = $"分组： {model.OwnerGroup?.Name} 连接: {model.IP}:{model.Port}";
                    this.recordLogService.AppendLog(ApplicationConstants.APPLICATION_GROUP_NAME, RecordLogOperate.Operate, RecordLogTrigger.Human, RecordLogConstants.OPERATE_SETTING_VIZ_CONNECTION, remark);

                    model.EndpointManager.Connect();
                }
            }, final: () =>
            {
                model.IsLoading = false;
            });
        }

        #endregion

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

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

        /// <summary>
        /// Viz引擎初始化完成消息
        /// </summary>
        /// <param name="msg">消息</param>
        private void OnVizPreviewReadyMessage(VizPreviewReadyMessage msg)
        {
            List<ConnGroupModel> groups = this.connService.LoadGroups();
            ApplicationDomainEx.ConnGroups.Clear();
            ApplicationDomainEx.ConnGroups.AddRange(groups);

            this.InitAndConnnectGroups();
        }

        /// <summary>
        /// 弹出消息
        /// </summary>
        /// <param name="msg">消息</param>
        private void OnAlertMessage(AlertMessage msg)
        {
            this.AlertMessage = msg.Message;
            ApplicationDomainEx.DelayManager.Wait("MainStatusViewModel.OnAlertMessage", 3, () =>
            {
                WPFHelper.BeginInvoke(() =>
                {
                    this.AlertMessage = null;
                });
            });
        }

        /// <summary>
        /// 初始化 & 连接
        /// </summary>
        private void InitAndConnnectGroups()
        {
            // 清理之前的连接
            foreach (ConnGroupModel group in this.ItemsSrouce)
            {
                foreach (ConnModel item in group.Items)
                {
                    if (item == ApplicationDomainEx.PreviewConn)
                        continue;

                    // 记录操作日志
                    string remark = $"分组： {item.OwnerGroup?.Name} 连接: {item.IP}:{item.Port}";
                    this.recordLogService.AppendLog(ApplicationConstants.APPLICATION_GROUP_NAME, RecordLogOperate.System, RecordLogTrigger.System, RecordLogConstants.OPERATE_SETTING_VIZ_DISCONNECTION, remark);

                    item.Dispose();
                }
            }

            this.ItemsSrouce.Clear();

            // 预览分组
            this.ItemsSrouce.Add(ApplicationDomainEx.PreviewConnGroup);

            // 其他分组
            foreach (ConnGroupModel group in ApplicationDomainEx.ConnGroups)
            {
                if (!group.IsEnabled)
                    continue;

                foreach (ConnModel item in group.Items)
                {
                    if (!item.IsEnabled)
                        continue;

                    item.InitEndpointManager(group, new VizEndpointManager(item.ConnID.ToString(), item.IP, item.Port));

                    // 启动连接
                    ThreadHelper.SafeRun(() =>
                    {
                        try
                        {
                            // 记录操作日志
                            string remark = $"分组： {item.OwnerGroup?.Name} 连接: {item.IP}:{item.Port}";
                            this.recordLogService.AppendLog(ApplicationConstants.APPLICATION_GROUP_NAME, RecordLogOperate.System, RecordLogTrigger.System, RecordLogConstants.OPERATE_SETTING_VIZ_CONNECTION, remark);

                            item.EndpointManager.Connect();
                        }
                        catch (Exception ex)
                        {
                            log.Error(ex);
                        }
                    });
                }

                this.ItemsSrouce.Add(group);
            }
        }
    }
}
