using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace GeneralGommunication
{
    /// <summary>
    /// 测量通讯速度模块
    /// </summary>
    public class CommSpeedMeasuring : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        /// <summary>
        /// 通讯速度 测量中
        /// </summary>
        public bool IsMeasuring { get; private set; }

        /// <summary>
        ///  通讯速度 byte/s
        /// </summary>
        public int CommSpeed { get; private set; }

        /// <summary>
        /// 通讯速度 单位 pack/s
        /// </summary>
        public int PackSpeed { get; private set; }


        int packCnt = 0;
        int recCnt = 0;
        Stopwatch stopwatch = new Stopwatch();
        protected CancellationTokenSource cancellationTokenSource;

        public void StartMeasure()
        {
            if (IsMeasuring)
                return;
            IsMeasuring = true;
            Reset();
            cancellationTokenSource = new CancellationTokenSource();
            //启动线程，测量速度
            Task.Factory.StartNew(MeasureTask, cancellationTokenSource.Token);
        }
        public void StopMeasure()
        {
            cancellationTokenSource.Cancel();
            //停止线程
            IsMeasuring = false;
        }
        void MeasureTask()
        {
            stopwatch.Start();
            while (!cancellationTokenSource.IsCancellationRequested)
            {
                if (stopwatch.Elapsed > TimeSpan.FromSeconds(1))
                {
                    int rcnt, pcnt;
                    double totalsec;
                    lock (this)
                    {
                        totalsec = stopwatch.Elapsed.TotalSeconds;
                        stopwatch.Restart();
                        rcnt = recCnt;
                        pcnt = packCnt;
                        recCnt = 0;
                        packCnt = 0;
                    }

                    //1秒均值
                    CommSpeed = (int)(rcnt / totalsec);
                    PackSpeed = (int)(pcnt / totalsec);
                }
                Task.Delay(100).Wait();
            }
            stopwatch.Stop();
        }

        /// <summary>
        /// 异常时调用
        /// </summary>
        public void Reset()
        {
            lock (this)
            {
                recCnt = 0;
                packCnt = 0;
            }
        }

        /// <summary>
        /// 需要在 RecMsg(byte[] recBuf) 中调用
        /// </summary>
        /// <param name="cnt"></param>
        public void IncRec(int cnt)
        {
            if (!IsMeasuring)
                return;
            lock (this)
            {
                recCnt += cnt;
            }
        }

        /// <summary>
        /// 需要在 ParsePack(pack); 后调用
        /// </summary>
        /// <param name="cnt"></param>
        public void IncPack(int cnt)
        {
            if (!IsMeasuring)
                return;
            lock (this)
            {
                packCnt += cnt;
            }
        }
    }
}
