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>();

        TimeSpan keepTime = TimeSpan.FromMinutes(6);
        /// <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;
            }
            keepTime = TimeSpan.FromMinutes(Math.Max(6, filterTime.TotalMinutes * 3));

            var now = DateTime.Now;
            Datas.RemoveAll(d => d.Time < now - keepTime);
            Datas.Add(new TempFilterData()
            {
                Ad = ad,
                FilterAd = ad,
                Time = now
            });
            double sum = 0;
            int cnt = 0;
            for (int i = 0; i < Datas.Count(); i++)
            {
                var d = Datas[Datas.Count()-1-i];
                if (d.Time >= (now - filterTime) && d.IsReset == false)
                {
                    sum += d.Ad;
                    cnt++;
                }
                else {
                    break;
                }
            }
            if (cnt > 0)
            {
                Datas.Last().FilterAd = (int)Math.Round(sum / cnt);
            }
            return Datas.Last().FilterAd;
        }

        /// <summary>
        /// 
        /// </summary>
        public void Reset()
        {
            var now = DateTime.Now;
            Datas.RemoveAll(d => d.Time < now - keepTime);
            Datas.Add(new TempFilterData() { IsReset = true, Time = DateTime.Now });
        }

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