using Aitex.Core.RT.IOCore;
using Aitex.Core.RT.SCCore;
using System;
using System.Text;

namespace MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Temps
{
    /// <summary>
    /// 会根据PM安装与否，执行合适的Log输出，DO输出，温度在规定次数内是否改变方法
    /// 此类作为一个测温类的对象使用，
    /// 初始化时传入的名称+温度下限+测温通道数，
    /// 1：名称会在Log中打印出来，2：传入温度<=最低温度时，认为温度发生变化
    /// </summary>
    public class TempBasFunction
    {
        private bool IsPM1Installed { get; set; }

        private bool IsPM2Installed { get; set; }

        private string DeviceName { get; set; }

        private float[] tempChangeCache;

        //硬件通道数
        private int NumberOfChannels;

        /// <summary>
        /// 统计温度相同次数
        /// </summary>
        private int noChangeNum;

        /// <summary>
        /// 记录温度不变时数据，最多记录10次
        /// </summary>
        private StringBuilder strNoChangeMeg = new();

        /// <summary>
        /// 测温硬件最低测试温度，传入温度为此数值，不进行温度数据变化对比
        /// </summary>
        private readonly double TempMin;

        /// <summary>
        /// 初始化
        /// </summary>
        /// <param name="deviceName">测温硬件名称</param>
        /// <param name="tempMin">最低温度显示，AE和昂坤都是600</param>
        public TempBasFunction(string deviceName , double tempMin,int numberOfChannels)
        {
            DeviceName = deviceName;
            TempMin = tempMin;
            NumberOfChannels = numberOfChannels;
            tempChangeCache = new float[NumberOfChannels];
            IsPM1Installed = SC.GetValue<bool>($"System.SetUp.IsPM1Installed");
            IsPM2Installed = SC.GetValue<bool>($"System.SetUp.IsPM2Installed");
        }

        public void PM1PM2PostLog(string str, Action<string, string, int> action)
        {
            if (IsPM1Installed)
                action("PM1", $"{DeviceName} {str}", 2);

            if (IsPM2Installed)
                action("PM2", $"{DeviceName} {str}", 2);
        }

        /// <summary>
        /// 操作DO_PyroCommunicationError信号为InterLock提供输出,DO输出为true时设备报警宕机
        /// </summary>
        /// <param name="isReset"></param>
        public void SetPm1Pm2IoForInterlock(bool isReset)
        {
            if (IsPM1Installed)
                IO.DO[$"PM1.DO_PyroCommunicationError"].SetValue(isReset, out _);
            if (IsPM2Installed)
                IO.DO[$"PM2.DO_PyroCommunicationError"].SetValue(isReset, out _);
        }

        /// <summary>
        /// 复位单个PM的DO信号
        /// </summary>
        /// <param name="pm"></param>
        /// <param name="isReset"></param>
        public void SetPmIoForInterlock(string pm, bool isReset)
        {
            string PM = pm.ToUpper();
            if (IsMP(PM))
               IO.DO[$"PM1.DO_PyroCommunicationError"].SetValue(isReset, out _);
        }

        /// <summary>
        /// 控制单个PM报警输出
        /// </summary>
        /// <param name="pm"></param>
        /// <param name="str"></param>
        /// <param name="action"></param>
        public void PMPostLog(string pm, string str, Action<string, string, int> action)
        {
            string PM = pm.ToUpper();
            if (IsMP(PM))
                action(PM, $"{DeviceName} {str}", 2);
        }

        private bool IsMP(string pm)
        {
            return (pm == "PM1" || pm == "PM2")? true : false;
        }

        /// <summary>
        /// 温度是否发生改变，返回数据不发生改变次数
        /// </summary>
        /// <param name="outputTemp"></param>
        /// <returns></returns>
        public int TempInvariantCount(float[] outputTemp, out string errorInf)
        {
            errorInf = "";
            if (noChangeNum > 999999)//防止数据溢出
                noChangeNum = 0;
            for (int i = 0; i < outputTemp.Length; i++)
            {
                if (outputTemp[i] <= TempMin)//低于温度下限，数据不做对比
                    continue;

                if (outputTemp[i] == tempChangeCache[i])
                {
                    if (noChangeNum < 10)//记录前10次的数据
                        strNoChangeMeg.Append($"#{i + 1}:{outputTemp[i]:0.00}   ");

                    errorInf = strNoChangeMeg.ToString();
                    return noChangeNum++;
                }
                tempChangeCache[i] = outputTemp[i];
            }

            //只要数据不同，就可以复位计数和缓存
            strNoChangeMeg.Clear();
            noChangeNum = 0;
            return 0;
        }
    }
}
