using Aitex.Core.RT.Log;
using Aitex.Core.Util;
using Aitex.Core.WCF;
using MECF.Framework.Common.MultiProcess.ProcessCenter;
using System;
using System.Collections.Generic;
using System.Text;

namespace MECF.Framework.Common.MultiProcess
{
    /// <summary>
    /// 用于限制同一区域的机台同时进行工艺的数量;
    /// 客户端首先问询服务端位置是否充足，若条件合适则向服务端进行预定操作；
    ///
    /// </summary>
    public class MultiProcessManager : Singleton<MultiProcessManager>
    {
        #region Variables

        /// <summary>
        /// 基数上限,一个RUN占用两个基数
        /// </summary>
        private const int Max_Heart_Num = 4;

        /// <summary>
        /// 设备离线次数
        /// </summary>
        private const int Min_OffLine_Num = 3;

        private const int Max_Heart_Bater_Time = 15;//秒

        private PeriodicJob _thread;

        protected readonly R_TRIG _connectionFailed = new();

        /// <summary>
        /// 腔体列表；同时RUN最多有2个
        /// </summary>
        private readonly List<PMProcessData> _processStateList = [];

        private static readonly object _lock = new object();

        #endregion Variables

        #region Constructors

        public MultiProcessManager()
        {
            var _thread = new PeriodicJob(8000, OnTimer, $"MultiProcessManager", true);
        }

        #endregion Constructors

        #region Methods

        public void Initialize(bool enableService)
        {
            MULTIPROCESS._multiprocessmanager = this;
            if (enableService)
            {
                Singleton<WcfServiceManager>.Instance.Initialize(new Type[1] { typeof(MultiProcessService) });
            }
        }

        private bool OnTimer()
        {
            lock (_lock)
            {
                foreach (var item in _processStateList)
                {
                    if (IsClientTimeOut(item.HeartBeatTime))
                    {
                        if (item.OffLineNum >= Min_OffLine_Num + 1)
                        {
                            item.IsOnline = false;
                            return true;
                        }
                        if (item.OffLineNum > Min_OffLine_Num)
                        {
                            item.IsOnline = false;
                            LOG.Write($"{item.SicMachineID} is offline over {item.OffLineNum} number of times ");
                        }
                        item.OffLineNum++;
                        LOG.Write($"{item.SicMachineID} is offline over {item.OffLineNum} number of times ");
                    }
                    else
                    {
                        item.IsOnline = true;
                        item.OffLineNum = 0;
                    }
                }
                return true;
            }
        }

        private bool IsClientTimeOut(DateTime heartBeatTime)
        {
            //timeA 表示需要计算
            DateTime timeB = DateTime.Now;    //获取当前时间
            TimeSpan ts = timeB - heartBeatTime;    //计算时间差
            return ts.TotalSeconds <= Max_Heart_Bater_Time ? false : true;
        }

        public List<string> QueryAllProcessInformation()
        {
            return PMProcessStateManager.GetProcessInformation(_processStateList);
        }

        public string QueryMyProcessInformation(string sicMachineName, string pmName)
        {
            return PMProcessStateManager.QueryMyProcessInformation(_processStateList, sicMachineName, pmName);
        }

        public List<PMProcessData> QueryAllProcessData()
        {
            List<PMProcessData> processDataList = new List<PMProcessData>();
            foreach (var item in _processStateList)
            {
                processDataList.Add((PMProcessData)item.Clone());
            }
            return processDataList;
        }

        public bool CanEnterProcessNow(string clientInformation, string sicMachineName, string pmName, string state, out string result)
        {
            //2024-2-18，需求变更，使用最大RUN数量作为上限
            lock (_lock)
            {
                result = "OK";
                return true;
                var info = QueryMyProcessInformation(sicMachineName, pmName);
                if (string.IsNullOrEmpty(info))
                {
                    result = $"不存在{sicMachineName}.{pmName}";
                    return false;
                }

                int heartBase = 2 + GetAllHeatBaseNum(out string infor);//添加初始基数2

                if (heartBase <= Max_Heart_Num)
                {
                    result = "OK";
                    LOG.Write($"{sicMachineName}.{pmName} request to {state} => Server PASS : Heart base= {heartBase}");
                    UpdateChamberState(clientInformation, sicMachineName, pmName, "Process", "2");
                    return true;
                }
                result = $"RUN基数超上限:{Max_Heart_Num} " + infor;
                LOG.Write(result);
                return false;
            }
        }

        public bool CanEnterProcessIdleNow(string clientInformation, string sicMachineName, string pmName, string state, out string result)
        {
            //2024-2-18，需求变更，此方法不维护
            result = "OK";
            return true;

            //lock (_lock)
            //{
            //    int heartBase = 1 + GetAllHeatBaseNum(out string infor);//添加初始基数1
            //    if (heartBase <= Max_Heart_Num)
            //    {
            //        result = "OK";
            //        UpdateChamberState(clientInformation, sicMachineName, pmName,"Idle", "1");
            //        return true;
            //    }
            //    result = $"加热基数超上限:{Max_Heart_Num} " + infor;
            //    return false;
            //}
        }

        public bool UpdateChamberState(string clientInformation, string sicMachineName, string pmName, string pmState, string runBase)
        {
            lock (_lock)
            {
                PMProcessData pmProcessData = new()
                {
                    SicMachineName = sicMachineName,
                    PmName = pmName,
                    PmRunState = runBase,
                    PmState = pmState,
                    SicMachineID = clientInformation,
                    IsOnline = true
                };
                return PMProcessStateManager.ProcessStateChangeUpdate(pmProcessData, _processStateList);
            }
        }

        private int GetAllHeatBaseNum(out string infor)
        {
            int heatBase = 0;
            StringBuilder sb = new StringBuilder();
            foreach (var pmProcessData in _processStateList)
            {
                heatBase += PMProcessStateManager.GetHeatBaseNum(pmProcessData);
                sb.Append($"{pmProcessData.SicMachineID} => {pmProcessData.PmState} ;");
            }
            infor = sb.ToString();
            return heatBase;
        }

        public void OffLineReset()
        {
            foreach (var pmProcessData in _processStateList)
            {
                if (!pmProcessData.IsOnline)
                    pmProcessData.Reset();
            }
        }

        #endregion Methods
    }
}