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;

namespace MECF.Framework.Common.MultiProcess.ProcessCenter
{
    /// <summary>
    /// Rt作为客户端与服务器进行通讯，定期发送设备状态并接受服务器信息；问询服务器是否可以进行Process操作
    /// </summary>
    public class MultiProcessClient : Singleton<MultiProcessClient>
    {
        #region Service


        private IMultiProcessService _service;

        public bool InProcess { get; set; }

        public IMultiProcessService Service
        {
            get
            {
                if (_service == null)
                {
                    if (InProcess)
                    {
                        _service = new MultiProcessService();
                    }
                    else
                    {
                        _service = new MultiProcessServiceClient();
                    }
                }
                return _service;
            }
        }
        #endregion

        #region Variables

        private readonly List<string> _runstates = new() {"Process", "PreProcess", "Paused" }; 

        private object _lock = new object();

        private readonly PeriodicJob _threadMonitor;

        private bool _isConnected = true;
        protected readonly R_TRIG _connectionTrig = new();

        private bool _isPM1Installed = false;
        private bool _isPM2Installed = false;

        private string _name = "Sic08";
        private string _info = "";

        private int _total = -1;
        private int _process = -1;
        private int _processidle = -1;
        private Dictionary<string, string> _allmachinestatedic = new();

        private bool PM1CanEnterProcess
        {
            get
            {
                lock (_lock)
                {
                    return true;
                    if (!_isConnected)
                    {
                        EV.PostWarningLog("MultiProcess", "Failed to Connect with MultiProcess Service");
                        return false;
                    }
                    string state = (string)DATA.Poll("PM1.Status");
                    if (state == null)
                        state = "";
                    string result;
                    bool temp = Service.CanEnterProcessNow(_name, "PM1", state, out result);
                    if (!temp)
                    {
                        EV.PostWarningLog("MultiProcessFail", result);
                    }
                    return temp;
                }
            }
        }

        private bool PM1CanEnterProcessIdle
        {
            get
            {
                lock (_lock)
                {
                    return true;
                    if (!_isConnected)
                    {
                        EV.PostWarningLog("MultiProcess", "Failed to Connect with MultiProcess Service");
                        return false;
                    }
                    string state = (string)DATA.Poll("PM1.Status");
                    if (state == null)
                        state = "";
                    string result;
                    bool temp = Service.CanEnterProcessIdleNow(_name, "PM1", state, out result);
                    if (!temp)
                    {
                        EV.PostWarningLog("MultiProcessFail", result);
                    }
                    return temp;
                }
            }
        }

        private bool PM2CanEnterProcess
        {
            get
            {
                return true;
                if (!_isConnected)
                {
                    EV.PostWarningLog("MultiProcess", "Failed to Connect with MultiProcess Service");
                    return false;
                }
                string state = (string)DATA.Poll("PM2.Status");
                if (state == null)
                    state = "";
                string result;
                bool temp = Service.CanEnterProcessNow(_name, "PM2", state, out result);
                if (!temp)
                {
                    EV.PostWarningLog("MultiProcessFail", result);
                }
                return temp;

            }
        }

        private bool PM2CanEnterProcessIdle
        {
            get
            {
                return true;
                string state = (string)DATA.Poll("PM2.Status");
                if (state == null)
                    state = "";
                string result;
                bool temp = Service.CanEnterProcessIdleNow(_name, "PM2", state, out result);
                if (!temp)
                {
                    EV.PostWarningLog("MultiProcessFail", result);
                }
                return temp;

            }
        }

        #endregion

        #region Properties

        #endregion

        #region Constructors

        public MultiProcessClient()
        {
            _threadMonitor = new PeriodicJob(5000, OnTimer, "MultiProcessHandleThread", false, true);
        }

        #endregion Constructors

        #region Methods

        /// <summary>
        /// RT作为客户端和外部服务器进行交互;注意初始化位置
        /// </summary>
        public void Initialize()
        {
            _isPM1Installed = SC.GetValue<bool>("System.SetUp.IsPM1Installed");
            _isPM2Installed = SC.GetValue<bool>("System.SetUp.IsPM2Installed");

            _name = SC.GetStringValue("System.MachineName");

            #region InitData

            DATA.Subscribe("MultiProcessClient.IsConnected", () => _isConnected, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe("MultiProcessClient.ServiceInfo", () => _info, SubscriptionAttribute.FLAG.IgnoreSaveDB);

            DATA.Subscribe("MultiProcessClient.PM1.CanEnterProcessNow", () => PM1CanEnterProcess, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe("MultiProcessClient.PM1.CanEnterProcessIdleNow", () => PM1CanEnterProcessIdle, SubscriptionAttribute.FLAG.IgnoreSaveDB);

            DATA.Subscribe("MultiProcessClient.PM2.CanEnterProcessNow", () => PM2CanEnterProcess, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe("MultiProcessClient.PM2.CanEnterProcessIdleNow", () => PM2CanEnterProcessIdle, SubscriptionAttribute.FLAG.IgnoreSaveDB);

            #endregion

            #region InitOp

            OP.Subscribe("MultiProcessClient.UpdateChamberState", UpdateChamberState2);

            #endregion

            var workenable = SC.GetValue<bool>("System.MultiProcessMode");
            if (workenable)
                _threadMonitor.Start();

            SC.RegisterValueChangedCallback("System.MultiProcessMode", (newValue) =>
            {
                bool workenable = false;
                if (bool.TryParse(newValue.ToString(), out workenable))
                {
                    if (workenable)
                    {
                        _threadMonitor.Start();
                    }
                    else
                    { 
                        _threadMonitor.Stop();
                    }

                }

            });
        }





        /// <summary>
        /// 实时发送本机腔体状态
        /// </summary>
        /// <returns></returns>
        private bool OnTimer()
        {
            //UpdateChamberState作为心跳，实时更新状态；更新成功后获取服务器数据
            if (UpdateChamberState())
            {
                GetMultiProcessInformation();
            }
            return true;
        }

        /// <summary>
        /// 实时收集Process信息
        /// </summary>
        private void GetMultiProcessInformation()
        {
            var list = MultiProcessClient.Instance.Service.QueryAllProcessInformation();
            if (list.Count!=0)
            {
                _allmachinestatedic.Clear();
            }
            foreach (var info in list)
            {
                if (info.StartsWith("State."))
                {
                    string temp = info.Substring(6);
                    string[] temps = temp.Split('.');
                    if (temps.Length == 3)
                    {
                        _allmachinestatedic[temps[0] + "." + temps[1]] = temps[2];
                    }
                }
                else if (info.StartsWith("Total."))
                {
                    int num = -1;
                    try
                    {
                        num = Convert.ToInt16(info.Substring(6));
                    }
                    catch (Exception)
                    {
                        ;
                    }
                    _total = num;
                }
                else if (info.StartsWith("Process."))
                {
                    int num = -1;
                    try
                    {
                        num = Convert.ToInt16(info.Substring(8));
                    }
                    catch (Exception)
                    {
                        ;
                    }
                    _process = num;
                }
                else if (info.StartsWith("ProcessIdle."))
                {
                    int num = -1;
                    try
                    {
                        num = Convert.ToInt16(info.Substring(12));
                    }
                    catch (Exception)
                    {
                        ;
                    }
                    _processidle = num;
                }
            }
            _info = $"Total Chamber:{_total};Processing Chamber:{_process};\r\nDetails:\r\n";
            foreach (var item in _allmachinestatedic)
            {
                _info += $"{item.Key} is {item.Value}\r\n";
            }
        }

        /// <summary>
        /// 发送腔体状态
        /// </summary>
        private bool UpdateChamberState2(string arg1, object[] args)
        {
            bool sendlog = _isConnected;
            for (int i = 0; i < 3; i++)
            {
                _isConnected = UpdateState(arg1, args);
                if (_isConnected)
                {
                    break;
                }
                else
                {
                    if (sendlog)
                    {
                        EV.PostInfoLog("MultiProcessClient", $"Failed Connect {i}");
                    }
                }
                    
            }
            
            _connectionTrig.CLK = !_isConnected;
            if (_connectionTrig.Q)
            {

                EV.PostWarningLog("MultiProcessClient", "Failed to Connect MultiProcess Service");
            }

            return _isConnected;

        }

        /// <summary>
        /// 发送腔体状态
        /// </summary>
        private bool UpdateChamberState()
        {
            bool sendlog = _isConnected;
            for (int i = 0; i < 3; i++)
            {
                _isConnected = UpdateState();
                if (_isConnected)
                {
                    break;
                }
                else
                {
                    if (sendlog)
                    {
                        EV.PostInfoLog("MultiProcessClient", $"Failed Connect {i}");
                    }
                }
            }

            _connectionTrig.CLK = !_isConnected;
            if (_connectionTrig.Q)
            {
                EV.PostWarningLog("MultiProcessClient", "Failed to Connect MultiProcess Service");
            }

            return _isConnected;

        }

        /// <summary>
        /// 更新服务器本机的当前状态
        /// </summary>
        /// <returns></returns>
        private bool UpdateState()
        {
            lock (_lock)
            {
                if (_isPM1Installed)
                {
                    string state = (string)DATA.Poll("PM1.Status");
                    if (state != null)
                    {
                        if (_runstates.Contains(state))
                        {
                            if (!Service.UpdateChamberState(_name, "PM1", state, "2"))
                            {
                                return false;
                            }
                        }
                        else if (!Service.UpdateChamberState(_name, "PM1", state, "0"))
                        {
                            return false;
                        }
                    }
                    else return false;
                }

                if (_isPM2Installed)
                {
                    string state = (string)DATA.Poll("PM2.Status");
                    if (state != null)
                    {
                        if (_runstates.Contains(state))
                        {
                            if (!Service.UpdateChamberState(_name, "PM2", state, "2"))
                            {
                                return false;
                            }
                        }
                        else if (!Service.UpdateChamberState(_name, "PM2", state, "0"))
                        {
                            return false;
                        }
                    }
                    else return false;
                }

                return true;
            }   
        }

        /// <summary>
        /// 通知服务器本机的当前状态
        /// </summary>
        /// <returns></returns>
        private bool UpdateState(string arg1, object[] args)
        {
            lock (_lock)
            {
                if (arg1 == "PM1")
                {
                    string state = (string)DATA.Poll("PM1.Status");
                    if (args.Length == 1)
                    {
                        if ((string)args[0] == "QuitHeating" || (string)args[0] == "QuitProcess")
                        {
                            if (!Service.UpdateChamberState(_name, "PM1",state, "0"))
                            {
                                return false;
                            }
                        }
                        else return false;
                    }
                    else return false;
                }
                else if (arg1 == "PM2")
                {
                    string state = (string)DATA.Poll("PM2.Status");
                    if (args.Length == 1)
                    {
                        if ((string)args[0] == "QuitHeating" || (string)args[0] == "QuitProcess")
                        {
                            if (!Service.UpdateChamberState(_name, "PM2", state, "0"))
                            {
                                return false;
                            }
                        }
                        else return false;
                    }
                    else return false;
                }

                return true;
            }
        }
        #endregion

    }
}
