using Aitex.Core.RT.DBCore;
using Aitex.Core.RT.Event;
using Aitex.Core.RT.Log;
using Aitex.Core.Util;
using MECF.Framework.Common.Account.Extends;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Xml.Linq;
using System.Xml;
using SciChart.Core.Extensions;

namespace MECF.Framework.Common.Aitex.Core.RT.EMS
{
    public class MaintainerEditor2 : XmlLoader
    {
        #region Variables

        /// <summary>
        /// 维护项列表
        /// </summary>
        private List<IMaintainer> _allMaintainerList = new();

        private List<MaintainerInfo> _allMaintainerInfoList = new();

        private Dictionary<string, List<MaintainerInfo>> _enabledmaintainerInfodic = new();

        private Dictionary<string, List<MaintainerInfo>> _allmaintainerInfodic = new();

        private List<MaintainerItemConfigInfo> _allMaintainerItemConfigList = new();

        Func<object, bool> _isSubscriptionAttribute;

        Func<PropertyInfo, bool> _hasSubscriptionAttribute;

        #endregion

        public MaintainerEditor2(string fileName) : base(fileName)
        {
            _isSubscriptionAttribute = attribute => attribute is SubscriptionAttribute;

            _hasSubscriptionAttribute = mi => mi.GetCustomAttributes(false).Any(_isSubscriptionAttribute);
        }

        #region Methods

        protected override void AnalyzeXml()
        {
            if (XmlDoc == null)
            {
                return;
            }

            #region 获取MaintenanceItem配置
            var ConfigX = XmlDoc.Element("root")?.Element("AllMaintainerItemConfigs");
            if (ConfigX == null)
            {
                return;
            }
            var maintainnamceItemsconfigX = from r in ConfigX.Descendants("MaintainerItemConfig")
                                            select (r);
            foreach (var itemX in maintainnamceItemsconfigX)
            {
                string parentName = itemX.Attribute("ParentName")?.Value;
                string name = itemX.Attribute("Name")?.Value;
                string uidstring = itemX.Attribute("UID")?.Value;
                string indexstring = itemX.Attribute("Index")?.Value;
                string description = itemX.Attribute("Description")?.Value ?? "";
                string defaultrecord = itemX.Attribute("DefaultRecord")?.Value ?? "";
                string filepath = itemX.Attribute("FilePath")?.Value ?? "";
                int index = 0;
                if (string.IsNullOrEmpty(name) || string.IsNullOrEmpty(indexstring))
                {
                    EV.PostWarningLog("Maintenance", $"XML failed:MaintainConfigSubItem Parameter Missing");
                    //log.error
                    continue;
                }
                if (!int.TryParse(indexstring, out index))
                {
                    EV.PostWarningLog("Maintenance", $"XML failed:MaintainConfigSubItem({name}) Parameter (Index) Parse failed;");
                    //log.error
                }

                MaintainerItemConfigInfo mi2 = new MaintainerItemConfigInfo(parentName, name, uidstring, index, description, defaultrecord, filepath);
                _allMaintainerItemConfigList.Add(mi2);
            }
            #endregion

            #region 获取Maintainer
            var maintainersX = from r in XmlDoc.Descendants("Maintainer")
                                 select (r);
            foreach (var maintainerX in maintainersX)
            {
                string maintainertype = maintainerX.Attribute("Type")?.Value??"";
                string maintainername = maintainerX.Attribute("Name")?.Value;
                string maintainerdescription = maintainerX.Attribute("Description")?.Value ?? "";
                string maintainermodule = maintainerX.Attribute("Module")?.Value ?? "";

                string maintainerindexstring = maintainerX.Attribute("Index")?.Value ?? "";
                string maintainerenablestring = maintainerX.Attribute("Enable")?.Value ?? "True";
                string maintainerstartdatestring = maintainerX.Attribute("StartDate")?.Value;
                string maintainerthresholdstring = maintainerX.Attribute("Threshold")?.Value;
                string maintainertimedisplayunitstring = maintainerX.Attribute("TimeDisplayUnit")?.Value;

                int maintainerindex = 0;
                bool maintainerenable = false;
                DateTime maintainerstartdate = DateTime.Now;
                double maintainerthreshold = 100;
                TimeUnit maintainertimedisplayunit = TimeUnit.Hours;

                if (string.IsNullOrEmpty(maintainertype) || 
                    string.IsNullOrEmpty(maintainername) || 
                    string.IsNullOrEmpty(maintainerstartdatestring) || 
                    string.IsNullOrEmpty(maintainerthresholdstring))
                {
                    EV.PostWarningLog("Maintenance", "XML failed:Plan Parameter Missing");
                    continue;
                }
                if (!bool.TryParse(maintainerenablestring, out maintainerenable))
                {
                    EV.PostWarningLog("Maintenance", $"XML failed:Plan {maintainername} Parameter (enable) Parse failed;");
                    //log.error
                }
                if (!DateTime.TryParse(maintainerstartdatestring, out maintainerstartdate))
                {
                    EV.PostWarningLog("Maintenance", $"XML failed:Plan {maintainername} Parameter (startdate) Parse failed;");
                    //log.error
                }
                if (!double.TryParse(maintainerthresholdstring, out maintainerthreshold))
                {
                    EV.PostWarningLog("Maintenance", $"XML failed:Plan {maintainername} Parameter (threshold) Parse failed;");
                    //log.error
                }
                if (!Enum.TryParse(maintainertimedisplayunitstring, out maintainertimedisplayunit))
                {
                    EV.PostWarningLog("Maintenance", $"XML failed:Plan {maintainername} Parameter (timedisplayunit) Parse failed;");
                    //log.error
                }
                if (!int.TryParse(maintainerindexstring, out maintainerindex))
                {
                    EV.PostWarningLog("Maintenance", $"XML failed:Plan {maintainername} Parameter (Index) Parse failed;");
                    //log.error
                }

                MaintainerItemCollection collection = new MaintainerItemCollection();

                var itemsX = from r in maintainerX.Descendants("MaintainerItem") select (r);
                foreach (var itemX in itemsX)
                {
                    string itemuidstring = itemX.Attribute("UID")?.Value ?? "";
                    string itemenablestring = itemX.Attribute("Enable")?.Value ?? "";
                    string itemdatetimestring = itemX.Attribute("MaintainedDateLatest")?.Value ?? "2000-1-1 0:0:0";

                    bool enable2 = false;
                    DateTime date2 = new DateTime(2000, 1, 1);

                    if (string.IsNullOrEmpty(itemuidstring))
                    {
                        EV.PostWarningLog("Maintenance", $"XML failed:Plan UID Parameter Missing");
                        //log.error
                        continue;
                    }
                    if (!bool.TryParse(itemenablestring, out enable2))
                    {
                        EV.PostWarningLog("Maintenance", $"XML failed:Plan {maintainername}:MaintainItem Parameter (enable) Parse failed;");
                        //log.error
                    }
                    DateTime.TryParse(itemdatetimestring, out date2);
                    var cinfo = _allMaintainerItemConfigList.Find(i => i.UID == itemuidstring);
                    if (cinfo != null)
                    {
                        MaintainerItem mi = new MaintainerItem(itemuidstring, enable2, date2, cinfo);
                        collection.AddMaintainerItem(mi);
                    }
                    else
                    {
                        EV.PostWarningLog("Maintenance", $"XML failed:Plan {maintainername}:MaintainItem{itemuidstring} Config Missing;");
                    }
                    
                }

                if (maintainertype == nameof(PresetMaintainer))
                {
                    PresetMaintainer pm = new PresetMaintainer(collection,
                    maintainername,
                    maintainermodule,
                    maintainerindex,
                    maintainerdescription,
                    maintainerenable,
                    maintainerstartdate,
                    maintainerthreshold,
                    maintainertimedisplayunit);

                    pm.OnSave += SaveXml;
                    _allMaintainerList.Add(pm);
                }
                else if (maintainertype == nameof(ProcessMaintainer))
                {
                    ProcessMaintainer pm = new ProcessMaintainer(collection,
                    maintainername,
                    maintainermodule,
                    maintainerindex,
                    maintainerdescription,
                    maintainerenable,
                    maintainerstartdate,
                    maintainerthreshold,
                    maintainertimedisplayunit);

                    pm.OnSave += SaveXml;
                    _allMaintainerList.Add(pm);
                }
                else if (maintainertype == nameof(CoatingMaintainer))
                {
                    CoatingMaintainer pm = new CoatingMaintainer(collection,
                    maintainername,
                    maintainermodule,
                    maintainerindex,
                    maintainerdescription,
                    maintainerenable,
                    maintainerstartdate,
                    maintainerthreshold,
                    maintainertimedisplayunit);

                    pm.OnSave += SaveXml;
                    _allMaintainerList.Add(pm);
                }

            }
            #endregion

            #region 配置初始化
            foreach (var item in _allMaintainerList)
            {
                _allMaintainerInfoList.Add(item.GetInfo());
            }

            foreach (var m in _allMaintainerInfoList)
            {
                //重新赋值config
                foreach (var item in m.MaintainerItemInfos)
                {
                    var c = _allMaintainerItemConfigList.Find(i => i.UID == item.UID);
                    if (c != null)
                    {
                        item.Config = c;
                    }
                }

                if (!_enabledmaintainerInfodic.ContainsKey(m.Name))
                {
                    _enabledmaintainerInfodic.Add(m.Name, new());
                    _allmaintainerInfodic.Add(m.Name, new List<MaintainerInfo>());
                    //_obmaintainerconfigenableinfodic.Add(m.Name, new());
                }

                _allmaintainerInfodic[m.Name].Add(m);
                if (m.Enable)
                {
                    _enabledmaintainerInfodic[m.Name].Add(m);
                }
            }

            OrderMaintainer();
            #endregion
            #region 检查后保存配置
            SaveXml();
            #endregion
        }

        protected bool SaveXml()
        {
            if (XmlDoc == null)
            {
                return false;
            }
            try
            {
                XmlDocument doc = new XmlDocument();
                doc.LoadXml("<?xml version=\"1.0\" encoding=\"utf-8\"?><root><MaintenanceGroup></MaintenanceGroup><AllMaintainerItemConfigs></AllMaintainerItemConfigs></root>");
                var root = doc.SelectSingleNode("root") as XmlElement;
                #region 保存_maintenancelist
                var groups = root.GetElementsByTagName("MaintenanceGroup")[0];
                foreach (var maintainer in _allMaintainerList)
                {
                    var xmlElement2 = doc.CreateElement("Maintainer");   //一级列表
                    var info = maintainer.GetInfo();

                    xmlElement2.SetAttribute("Type", info.Type);
                    xmlElement2.SetAttribute("Name", info.Name);
                    xmlElement2.SetAttribute("Description", info.Description);
                    xmlElement2.SetAttribute("Index", info.Index.ToString());
                    if (!string.IsNullOrEmpty(info.Module))
                    {
                        xmlElement2.SetAttribute("Module", info.Module);
                    }
                    xmlElement2.SetAttribute("Enable", info.Enable.ToString());
                    xmlElement2.SetAttribute("StartDate", info.StartDate.ToString());
                    xmlElement2.SetAttribute("Threshold", info.Threshold.ToString());
                    xmlElement2.SetAttribute("TimeDisplayUnit", info.TimeDisplayUnit.ToString());
                    var ilist = maintainer.GetAllMaintainerItems();

                    foreach (var item2 in ilist)
                    {
                        var xmlElement3 = doc.CreateElement("MaintainerItem");    //三级列表
                        xmlElement3.SetAttribute("UID", item2.UID.ToString());
                        //xmlElement3.SetAttribute("Name", item2.Name);
                        xmlElement3.SetAttribute("MaintainedDateLatest", item2.MaintainedDate.ToString());
                        xmlElement3.SetAttribute("Enable", item2.Enable.ToString());
                        xmlElement2.AppendChild(xmlElement3);
                    }

                    groups.AppendChild(xmlElement2);
                }
                
                #endregion
                #region 保存_maintenanceitemconfiglist

                var configgroups = root.GetElementsByTagName("AllMaintainerItemConfigs")[0];
                foreach (var item in _allMaintainerItemConfigList)
                {
                    var xmlElement = doc.CreateElement("MaintainerItemConfig");    //二级列表
                    xmlElement.SetAttribute("UID", item.UID);
                    xmlElement.SetAttribute("ParentName", item.ParentName);
                    xmlElement.SetAttribute("Name", item.Name);
                    xmlElement.SetAttribute("Index", item.Index.ToString());
                    xmlElement.SetAttribute("Description", item.Description);
                    xmlElement.SetAttribute("DefaultRecord", item.DefaultRecord);
                    xmlElement.SetAttribute("FilePath", item.FilePath);
                    configgroups.AppendChild(xmlElement);
                }

                #endregion

                doc.Save(FileName);

                XmlDoc = XDocument.Load(FileName);
            }
            catch (Exception ex)
            {
                LOG.Write(ex);
                return false;
            }
            return true;
        }

        private void OrderMaintainer()
        {
            _enabledmaintainerInfodic.ForEachDo(i =>
            {
                var temp = i.Value.OrderBy(i => i.Index).ToList();
                i.Value.Clear();
                foreach (var item in temp)
                {
                    i.Value.Add(item);
                }
            });
            _allmaintainerInfodic.ForEachDo(i => {
                var temp = i.Value.OrderBy(i => i.Index).ToList();
                i.Value.Clear();
                i.Value.AddRange(temp);
            });
        }

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


        public List<MaintainerItemConfigInfo> GetAllMaintainerConfigItemList()
        {
            return _allMaintainerItemConfigList;
        }

        public bool SetMaintain(string type,string name, string module, string parent, string itemname, string itemuid, DateTime date, string role, string detial)
        {
            int index = _allMaintainerList.FindIndex(i =>i.EqualsNameModule(type,name,module));
            if (index == -1)
                return false;
            if(_allMaintainerList[index].SetMaintain(itemuid,date))
            {
                string s = name + (module == "" ? "" : ("." + module));
                EV.PostInfoLog("Maintenance", $"Item {parent}-{itemname}({itemuid}) in Plan {s} is Maintained");

                #region DATABASE

                string cmd = string.Format("Insert into \"maintenance_event_data\"" +
                    "(\"planname\",\"planmodule\",\"itemparentname\",\"itemname\",\"uid\",\"createtime\",\"role\",\"detial\")" +
                    " values('{0}','{1}','{2}','{3}','{4}','{5}','{6}','{7}')", name, module, parent, itemname, itemuid, date.ToString("yyyy/MM/dd HH:mm:ss.fff"), role, detial);

                int result = DB.ExecuteNonQuery(cmd);
                if (result <= 0)
                {
                    EV.PostWarningLog("Maintenance", $"database execution faile => code: {cmd}");
                }
                #endregion

                return SaveXml();
            }
            else return false;
           
        }

        #region 维护项增删改

        public bool ExchangeMaintainItemIndex(string uid1, string uid2)
        {
            var item1 = _allMaintainerItemConfigList.Find(i => i.UID == uid1);
            var item2 = _allMaintainerItemConfigList.Find(i => i.UID == uid2);

            if (item1!=null && item2 !=null)
            {
                int tempindex = item1.Index;
                item1.Index = item2.Index;
                item2.Index = tempindex;

                _allMaintainerList.ForEachDo(i => i.SortItemInfo());
            }

            EV.PostInfoLog("Maintenance", $"Maintainer {uid1} & {uid2} Index is exchanged ");

            return SaveXml();
        }

        /// <summary>
        /// 二级维护项enable设置，根据名称和id确认唯一性
        /// </summary>
        /// <param name="type"></param>
        /// <param name="name"></param>
        /// <param name="module"></param>
        /// <param name="itemuid"></param>
        /// <param name="enable"></param>
        /// <returns></returns>
        public bool SetMaintainItemEnable(string type,string name, string module, string itemuid, bool enable)
        {
            int index = _allMaintainerList.FindIndex(i => i.EqualsNameModule(type, name, module));
            if (index == -1)
                return false;
            if (!_allMaintainerList[index].SetMaintainerItemEnable(itemuid, enable))
            {
                return false;
            } 

            string s = name + (module == "" ? "" : ("." + module));
            string result = enable ? "Enable" : "Disable";
            EV.PostInfoLog("Maintenance", $"Item {itemuid} in Plan {s} is {result}");

            return SaveXml();
        }

        /// <summary>
        /// 修改Item参数
        /// </summary>
        /// <param name="parentname"></param>
        /// <param name="name"></param>
        /// <param name="itemuid"></param>
        /// <param name="itemindex"></param>
        /// <param name="description"></param>
        /// <param name="defaultrecord"></param>
        /// <param name="filepath"></param>
        /// <returns></returns>
        public bool SetMaintainItemParas(string parentname, string name, string itemuid, int itemindex, string description, string defaultrecord, string filepath)
        {
            int index = _allMaintainerItemConfigList.FindIndex(i => i.UID == itemuid);
            if (index == -1)
                return false;

            _allMaintainerItemConfigList[index].ParentName = parentname;
            _allMaintainerItemConfigList[index].Name = name;
            if (_allMaintainerItemConfigList[index].Index != itemindex)
            {
                _allMaintainerList.ForEachDo(i=>i.SortItemInfo());
                _allMaintainerItemConfigList[index].Index = itemindex;
            }
            
            _allMaintainerItemConfigList[index].Description = description;
            _allMaintainerItemConfigList[index].DefaultRecord = defaultrecord;
            _allMaintainerItemConfigList[index].FilePath = filepath;

            EV.PostInfoLog("Maintenance", $"Item {itemuid} Parameters is changed ");

            return SaveXml();
        }

        /// <summary>
        /// 新增Item
        /// </summary>
        /// <param name="parentname"></param>
        /// <param name="name"></param>
        /// <param name="itemuid"></param>
        /// <param name="itemindex"></param>
        /// <param name="description"></param>
        /// <param name="defaultrecord"></param>
        /// <param name="filepath"></param>
        /// <returns></returns>
        public bool AddMaintainItem(string parentname ,string name, string itemuid, int itemindex, string description, string defaultrecord, string filepath)
        {
            MaintainerItemConfigInfo newconfigitem = new MaintainerItemConfigInfo(parentname, name,itemuid, itemindex, description, defaultrecord,filepath);
            _allMaintainerItemConfigList.Add(newconfigitem);

            foreach (var item in _allMaintainerList)
            {
                item.AddMaintainerItem(new MaintainerItem(itemuid,false,new DateTime(2000,1,1),newconfigitem));
            }
            return SaveXml();
        }

        /// <summary>
        /// 删除Item
        /// </summary>
        /// <param name="itemuid"></param>
        /// <returns></returns>
        public bool DeleteMaintainItem(string itemuid)
        {
            foreach (var ma in _allMaintainerList)
            {
                ma.RemoveMaintainerItem(itemuid);
            }

            int index = _allMaintainerItemConfigList.FindIndex(i => i.UID == itemuid);
            if (index == -1)
                return false;

            _allMaintainerItemConfigList.RemoveAt(index);
            
            EV.PostInfoLog("Maintenance", $"Maintenance Item {itemuid} deleted.");
            return SaveXml();
        }

        #endregion

        #region Plan增删改

        public bool SetMaintainerParas(string type,string name, string oldmodule, string newmodule, int _index, bool enable, string description, DateTime date, double threshold, TimeUnit timeunit)
        {
            int index = _allMaintainerList.FindIndex(i => i.EqualsNameModule(type, name, oldmodule));
            if (index == -1)
                return false;
            var info = _allMaintainerList[index].GetInfo();
            info.Module = newmodule;
            info.Description = description;
            info.Enable = enable;
            info.Index = _index;
            info.TimeDisplayUnit = timeunit;

            if (info.Threshold != threshold)
            {
                _allMaintainerList[index].SetThreshold(threshold, timeunit);
            }

            if (info.StartDate != date)
            {
                _allMaintainerList[index].SetStartDate(date);
            }

            _allMaintainerList[index].UpdateInfo();
            //if (_allMaintainerList[index] is PresetMaintainer pm1)
            //    pm1.UpdateInfo();
            //else if (_allMaintainerList[index] is ProcessMaintainer pm2)
            //    pm2.UpdateInfo();
            //else if (_allMaintainerList[index] is CoatingMaintainer pm3)
            //    pm3.UpdateInfo();

            EV.PostInfoLog("Maintenance", $"{info.DisplayName} Parameters is changed ");
            return SaveXml();
        }

        public bool AddMaintainer(string type,string name, string module, int _index ,bool enable, string description, DateTime date, double threshold, TimeUnit timeunit)
        {
            //ui 调用此函数前已判断重复性
            var mc = new MaintainerItemCollection();
            foreach (var maintainercitem in _allMaintainerItemConfigList)
            {
                mc.AddMaintainerItem(new MaintainerItem(maintainercitem.UID, false, new DateTime(2020, 1, 1), maintainercitem));
            }

            if (type == nameof(PresetMaintainer))
            {
                var plan = new PresetMaintainer(mc, name, module, _index, description, enable, date, threshold, timeunit);
                plan.OnSave += SaveXml;
                plan.UpdateInfo();

                _allMaintainerList.Add(plan);
            }
            else if (type == nameof(ProcessMaintainer))
            {
                var pm = new ProcessMaintainer(mc, name, module, _index, description, enable, date, threshold, timeunit);
                pm.OnSave += SaveXml;
                pm.UpdateInfo();

                _allMaintainerList.Add(pm);
            }
            else if (type == nameof(CoatingMaintainer))
            {
                var pm = new CoatingMaintainer(mc, name, module, _index, description, enable, date, threshold, timeunit);
                pm.OnSave += SaveXml;
                pm.UpdateInfo();

                _allMaintainerList.Add(pm);
            }

            string s = name + (module == "" ? "" : ("." + module));
            EV.PostInfoLog("Maintenance", $"Plan {s} created");
            return SaveXml();
        }

        public bool DeleteMaintainer(string type,string name, string module)
        {
            int index = _allMaintainerList.FindIndex(i => i.EqualsNameModule(type, name, module));
            if (index == -1)
                return false;

            if (_allMaintainerList.Remove(_allMaintainerList[index]))
            {
                string s = name + (module == "" ? "" : ("." + module));
                EV.PostInfoLog("Maintenance", $"Plan {s} Delete");

                return SaveXml();
            }
            else return false;
        }

        #endregion

        #endregion
    }
}
