using Aitex.Common.Util;
using Aitex.Core.RT.DataCenter;
using Aitex.Core.RT.Event;
using Aitex.Core.RT.OperationCenter;
using Aitex.Core.RT.SCCore;
using Aitex.Core.Util;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Xml;

namespace MECF.Framework.Common.Aitex.Core.RT.EMS
{
    public class MaintainManager2 : Singleton<MaintainManager2>
    {
        #region Variables
        private readonly string _MaintainFilePath;
        private PeriodicJob _threadMonitor;
        private MaintainerEditor2 _editor;
        private DateTime _listChangedHandShake = DateTime.Now;
        private DateTime _handShake = DateTime.Now;
        #endregion

        #region Constructors
        public MaintainManager2()
        {
            _MaintainFilePath = Path.Combine(PathManager.GetMaintainFilePath(), "Maintain.xml");
            var fileInfo = new FileInfo(_MaintainFilePath);
            if (!fileInfo.Directory.Exists)
            {
                fileInfo.Directory.Create();
            }
            if (!fileInfo.Exists)
            {
                XmlDocument _MaintainXML = new XmlDocument();
                _MaintainXML.LoadXml("<?xml version=\"1.0\" encoding=\"utf-8\"?><root><MaintenanceGroup></MaintenanceGroup><AllMaintainerItemConfigs></AllMaintainerItemConfigs></root>");
                _MaintainXML.Save(_MaintainFilePath);
            }

        }
        #endregion

        #region Properties
        #endregion

        #region Methods
        public void Initialize()
        {
            _editor = new MaintainerEditor2(_MaintainFilePath);
            _editor.Load();

            #region OP_Subscribe

            OP.Subscribe("MaintainManager.SetMaintain", delegate (string cmd, object[] args)
            {
                _editor.SetMaintain((string)args[0], 
                    (string)args[1],
                    (string)args[2],
                    (string)args[3],
                    (string)args[4],
                    (string)args[5],
                    (DateTime)args[6],
                    (string)args[7],
                    (string)args[8]);
                RestartMonitor();
                return true;
            });

            OP.Subscribe("MaintainManager.OpenFile", delegate (string cmd, object[] args)
            {
                OpenFile((string)args[0]);
                return true;
            });

            #region 配置项增删改

            OP.Subscribe("MaintainManager.ExchangeMaintainItemIndex", delegate (string cmd, object[] args)
            {
                _editor.ExchangeMaintainItemIndex((string)args[0], (string)args[1]);
                RestartMonitor();
                _listChangedHandShake = DateTime.Now;
                return true;
            });

            OP.Subscribe("MaintainManager.SetMaintainItemEnable", delegate (string cmd, object[] args)
            {
                _editor.SetMaintainItemEnable((string)args[0], (string)args[1], (string)args[2], (string)args[3], (bool)args[4]);
                RestartMonitor();
                _listChangedHandShake = DateTime.Now;
                return true;
            });

            OP.Subscribe("MaintainManager.SetMaintainItemParas", delegate (string cmd, object[] args)
            {
                _editor.SetMaintainItemParas((string)args[0], (string)args[1], (string)args[2], (int)args[3], (string)args[4],  (string)args[5], (string)args[6]);
                RestartMonitor();
                return true;
            });

            OP.Subscribe("MaintainManager.AddMaintainItem", delegate (string cmd, object[] args)
            {
                _editor.AddMaintainItem((string)args[0], (string)args[1], (string)args[2], (int)args[3], (string)args[4], (string)args[5], (string)args[6]);
                RestartMonitor();
                return true;
            });

            OP.Subscribe("MaintainManager.DeleteMaintainItem", delegate (string cmd, object[] args)
            {
                _editor.DeleteMaintainItem((string)args[0]);
                RestartMonitor();
                _listChangedHandShake = DateTime.Now;
                return true;
            });

            #endregion

            #region Plan增删改

            OP.Subscribe("MaintainManager.SetMaintainerParas", delegate (string cmd, object[] args)
            {
                _editor.SetMaintainerParas((string)args[0], (string)args[1], (string)args[2], (string)args[3], (int)args[4], (bool)args[5], (string)args[6],
                    (DateTime)args[7], (double)args[8], (TimeUnit)args[9]);
                _listChangedHandShake = DateTime.Now;
                RestartMonitor();
                return true;
            });

            OP.Subscribe("MaintainManager.AddMaintainer", delegate (string cmd, object[] args)
            {
                _editor.AddMaintainer((string)args[0], (string)args[1], (string)args[2], (int)args[3], (bool)args[4], (string)args[5],
                    (DateTime)args[6], (double)args[7], (TimeUnit)args[8]);
                _listChangedHandShake = DateTime.Now;
                RestartMonitor();
                return true;
            });

            OP.Subscribe("MaintainManager.DeleteMaintainer", delegate (string cmd, object[] args)
            {
                _editor.DeleteMaintainer((string)args[0], (string)args[1], (string)args[2]);
                _listChangedHandShake = DateTime.Now;
                RestartMonitor();
                return true;
            });
            #endregion

            #endregion

            DataSubscribe();

            //第一次执行监控
            OnTimer();

            _threadMonitor = new(10000, OnTimer, "MaintainMonitorThread", true, true);

            MAINTAIN.maintainManager = this;

        }

        private string MaintenanceCheck()
        {
            string s = "";
            foreach (var p in _editor.GetAllMaintainerList())
            {
                var info = p.GetInfo();
                if (info.IsTrigger)
                {
                    s += "[" + info.DisplayName + "]\r\n";
                }
            }
            if (s != "")
            {
                bool iswarning = true;
                if (SC.ContainsItem("System.IgnoreMaintainTimeOutWarning"))
                {
                    iswarning = !SC.GetValue<bool>("System.IgnoreMaintainTimeOutWarning");
                }
                if (iswarning)
                    EV.PostWarningLog("Maintenance", "There are UnMaintainItems in Plan\r\n" + s
                        + "please check as soon as possible.");
                else
                {
                    EV.PostInfoLog("Maintenance", "There are UnMaintainItems in Plan\r\n" + s
                    + "please check as soon as possible.");
                    return "";
                }

            }
            return s;
        }

        private void DataSubscribe()
        {
            DATA.Subscribe("MaintainManager.ListChangedHandShake", () => _listChangedHandShake, SubscriptionAttribute.FLAG.IgnoreSaveDB);

            DATA.Subscribe("MaintainManager.ItemHandShake", () => _handShake, SubscriptionAttribute.FLAG.IgnoreSaveDB);

            DATA.Subscribe("MaintainManager.MaintenanceCheck", MaintenanceCheck, SubscriptionAttribute.FLAG.IgnoreSaveDB);

            DATA.Subscribe("MaintainManager.MaintainerInfos", GetAllMaintainerInfos, SubscriptionAttribute.FLAG.IgnoreSaveDB);

            DATA.Subscribe("MaintainManager.MaintainerConfigItems", GetAllMaintainConfigItems, SubscriptionAttribute.FLAG.IgnoreSaveDB);

        }

        private List<MaintainerInfo> GetAllMaintainerInfos()
        {
            return _editor.GetAllMaintainerList().Select(i=>i.GetInfo()).ToList();
        }

        private bool OnTimer()
        {
            var maintainers = _editor.GetAllMaintainerList();
            maintainers.ForEach(x => { 
                if (x is PresetMaintainer plan) 
                {
                    plan.Monitor();
                }
                else if (x is ProcessMaintainer pm)
                {
                    pm.Monitor();
                }
                else if (x is CoatingMaintainer co)
                {
                    co.Monitor();
                }
            });
            _handShake = DateTime.Now;
            return true;
        }

        private void RestartMonitor()
        {
            _threadMonitor.Stop();
            _threadMonitor = new(10000, OnTimer, "MaintainMonitorThread", true, true);
        }

        public List<IMaintainer> GetAllMaintainerList()
        {
            return _editor.GetAllMaintainerList();
        }

        public List<MaintainerItemConfigInfo> GetAllMaintainConfigItems()
        {
            return _editor.GetAllMaintainerConfigItemList();
        }

        private void OpenFile(string name)
        {
            string filepath = Path.Combine(PathManager.GetMaintainFilePath(), name);
            if (!File.Exists(filepath))
            {
                EV.PostWarningLog("Maintenance", $"Not file in Path:" + filepath);
                return;
            }
            try
            {
                System.Diagnostics.Process.Start(filepath);
            }
            catch (Exception ex)
            {
                EV.PostWarningLog("Maintenance", $"Can not Open file in Path:{filepath},Reason:{ex}");
                return;
            }

        }
        #endregion
    }
}
