using FLY.Thick.Base.IService;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;

namespace FLY.Thick.Base.Server
{

    /// <summary>
    /// 样品修正 滤波
    /// </summary>
    public class TempFilter
    {
        DateTime sampleTime;
        int sampleFailure;
        int swfilterCnt;

        /// <summary>
        /// 滤波器
        /// </summary>
        class SWFilter
        {
            /// <summary>
            /// 缓存区
            /// </summary>
            int[] buffer;
            /// <summary>
            /// 缓存区大小
            /// </summary>
            int bufferSize;
            /// <summary>
            /// 队列尾
            /// </summary>
            int lastData;
            /// <summary>
            /// 默认值
            /// </summary>
            int initvalue;

            public SWFilter(int buffersize)
            {
                this.bufferSize = buffersize;

                buffer = new int[buffersize];
            }

            public int CalValue(int window)
            {
                double sum = 0;
                int cnt = 0;
                int p = lastData;
                while (window > 0)
                {
                    if (buffer[p] != initvalue)
                    {
                        sum += buffer[p];
                        cnt++;
                    }
                    p--;
                    if (p < 0) p = bufferSize - 1;
                    window--;
                }
                if (cnt == 0) return initvalue;
                return (int)Math.Round(sum / cnt);
            }

            public void Clear(int initvalue)
            {
                for (int i = 0; i < bufferSize; i++)
                    buffer[i] = initvalue;
                this.initvalue = initvalue;
                lastData = bufferSize - 1;
            }

            public void PushData(int value)
            {
                lastData++;
                if (lastData >= bufferSize)
                    lastData = 0;
                buffer[lastData] = value;
            }

            public void SetSize(int buffersize) 
            {
                if (this.bufferSize != buffersize) 
                {
                    this.bufferSize = buffersize;

                    buffer = new int[buffersize];

                    Clear(initvalue);
                }
            }
        }
        SWFilter swfilter;
        int tempBIndex;
        int[] tempBuf = new int[3];
        /// <summary>
        /// 前一个AD值
        /// </summary>
        int preValue;

        /// <summary>
        /// 
        /// </summary>
        public TempFilter()
        {
            sampleFailure = 0;
            swfilterCnt = 3;
            tempBIndex = -1;
            swfilter = new SWFilter(50);
            swfilter.Clear(-1);
            preValue = -1;
        }

        /// <summary>
        /// 复位失败次数
        /// </summary>
        public void ResetSampleFailure()
        {
            sampleFailure = 0;
        }
        
        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public bool IsSampleFailure()
        {
            if (sampleFailure < 0) return true;
            return false;
        }

        /// <summary>
        /// 输入原始AD值，输出滤波后AD值
        /// </summary>
        /// <param name="ad"></param>
        /// <returns></returns>
        public int CalSampleAD(int ad) 
        {
            return CalSampleAD(ad, out int originAD);
        }
        
        /// <summary>
        /// 输入原始AD值，输出滤波后AD值
        /// </summary>
        /// <param name="ad"></param>
        /// <param name="originAD"></param>
        /// <returns></returns>
        public int CalSampleAD(int ad, out int originAD)
        {
            originAD = 0;
            int delta;
            TimeSpan ts = TimeSpan.MaxValue;
            DateTime dt = DateTime.Now;

            switch (sampleFailure)
            {
                case 0:
                    sampleTime = dt;
                    sampleFailure = 1;
                    break;
                default:
                    dt = DateTime.Now;
                    ts = dt.Subtract(sampleTime);
                    sampleTime = dt;
                    break;
            }
            if ((ts.TotalMinutes > 30) || (preValue < 0))
            {
                preValue = ad;
                tempBIndex = -1;
                swfilter.Clear(-1);
                swfilter.PushData(preValue);

                originAD = ad;
                return ad;
            }
            delta = Math.Abs(ad - preValue);

            if (delta > 0.01 * Math.Abs(preValue))//跳到超过 1% ，有问题
            {
                if (tempBIndex < 1)		//  突变!! 需要2次确认 因为可能只是很大的噪声
                {
                    tempBIndex++;
                    tempBuf[tempBIndex] = ad;
                    return (int)preValue;
                }
                else
                {
                    preValue = ad;
                    sampleFailure = -1;
                    swfilter.Clear(-1);
                    swfilter.PushData(preValue);
                    originAD = ad;
                    return ad;
                }
            }
            //2013.04.19
            //
            //	if( delta > 0.008*preValue )trustFactor = 0.14;
            //	else if( delta > 0.006*preValue )trustFactor = 0.175;
            //	else if( delta > 0.004*preValue )trustFactor = 0.23;
            //	else if( delta > 0.002*preValue )trustFactor = 0.35;
            //	else if( delta > 0.001*preValue )trustFactor = 0.6;
            //	else trustFactor = 0.9;
            //	if( originAD )*originAD = (long)(preValue + delta * sign * trustFactor + 0.5);
            //	SWFilterPushData( swfilter, (long)(preValue + delta * sign * trustFactor + 0.5));
            //	preValue = ExponentialFilter( preValue, preValue+delta*sign*trustFactor, sysParam.swfilterConst );
            ////	preValue = (double)CalSWFilterValue( swfilter, 10 );

            tempBIndex = -1;
            //2013.04.19	
            originAD = ad;
            swfilter.PushData(ad);
            preValue = swfilter.CalValue(swfilterCnt);
            return preValue;
        }
        
        /// <summary>
        /// 移动滤波窗口大小
        /// </summary>
        /// <param name="window"></param>
        public void SetWindow(int window) 
        {
            if (window < 50)
                swfilterCnt = window;
        }
    }



    /// <summary>
    /// 样品修正 滤波, 返回N分钟内数据的均值。
    /// 如果波动较大，提示异常
    /// </summary>
    public class TempFilter2
    {
        List<TempFilterData> Datas = new List<TempFilterData>();
        const int KeepTimeMin = 6;
        const int KeepCount = 9;
        TimeSpan keepTime = TimeSpan.FromMinutes(KeepTimeMin);

        /// <summary>
        /// 
        /// </summary>
        public TempFilter2()
        {

        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="ad">原始AD</param>
        /// <param name="filterTime">滤波时间</param>
        /// <returns>滤波后Ad</returns>
        public int CalSampleAD(int ad, TimeSpan filterTime)
        {
            
            if (filterTime.TotalSeconds <= 0)
            {
                filterTime = TimeSpan.Zero;
            }
            var now = DateTime.Now;
            keepTime = TimeSpan.FromMinutes(Math.Max(KeepTimeMin, filterTime.TotalMinutes * 3));
            
            KeepSize();
            
            Datas.Add(new TempFilterData()
            {
                Ad = ad,
                FilterAd = ad,
                Time = now
            });
            double sum = ad;
            int cnt = 1;
            for (int i = 1; i < Datas.Count(); i++)
            {
                int index = Datas.Count() - 1 - i;
                var d = Datas[index];
                if (d.IsReset) {
                    //这个是reset 信号，退出
                    break;
                }
                if (d.Time < (now - filterTime))
                {
                    //太久了，退出
                    break;
                }

                sum += d.Ad;
                cnt++;
            }
            
            ad = (int)Math.Round(sum / cnt);
            Datas.Last().FilterAd = ad;

            return ad;
        }

        /// <summary>
        /// 
        /// </summary>
        public void Reset()
        {
            KeepSize();
            if (Datas.Count > 0 && !Datas.Last().IsReset)
            {
                //上一次是复位信号，就不需要再添加一个复位信号了
                Datas.Add(new TempFilterData() { IsReset = true, Time = DateTime.Now });
            }
        }
        void KeepSize() 
        {
            var now = DateTime.Now;
            int index = Datas.FindIndex(d => d.Time >= now - keepTime);
            if (index <= 0)
                return;
            //小于index, 都是要删除的
            //但必须保证删除后 Datas.Length >=10
            int len = Datas.Count() - index;
            if (len < KeepCount)
                index = Datas.Count() - KeepCount;
            if (index <= 0)
                return;
            Datas.RemoveRange(0, index);
        }


        public List<TempFilterData> GetDatas()
        {
            return Datas;
        }

        public int GetLastAd(DateTime time) 
        {
            for (int i = 1; i < Datas.Count; i++)
            {
                int index = Datas.Count() - 1 - i;
                var d = Datas[index];
                if (d.Time < time)
                    return -1;//时间太早了，没有数据

                if (Datas[index].IsReset)
                    continue;
                return d.Ad;
            }
            return -1;//没有数据
        }
    }
}
