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

namespace VIZ.Framework.Core
{
    /// <summary>
    /// FPS计算辅助类
    /// </summary>
    public class FPSHelper : ModelBase, IDisposable
    {
        /// <summary>
        /// 所有的辅助类
        /// </summary>
        private readonly static List<FPSHelper> allHelpers = new List<FPSHelper>();

        public FPSHelper()
        {
            lock (allHelpers)
            {
                allHelpers.Add(this);
            }
        }

        #region Duration -- 持续时间（单位：秒）

        private int duration = 5;
        /// <summary>
        /// 持续时间（单位：秒）
        /// </summary>
        public int Duration
        {
            get { return duration; }
            set { duration = value; this.RaisePropertyChanged(nameof(Duration)); }
        }

        #endregion

        #region FPS -- 当前FPS

        private int fps;
        /// <summary>
        /// 当前FPS
        /// </summary>
        public int FPS
        {
            get { return fps; }
            set { fps = value; this.RaisePropertySaveChanged(nameof(FPS)); }
        }

        #endregion

        /// <summary>
        /// 帧数
        /// </summary>
        private int frameCount;

        /// <summary>
        /// 帧总数
        /// </summary>
        private int frameCountHistTotal;

        /// <summary>
        /// 计时器
        /// </summary>
        private Stopwatch stopwatch = new Stopwatch();

        /// <summary>
        /// 最后一次帧时间
        /// </summary>
        private long lastFrameTime;

        /// <summary>
        /// 帧数量列表
        /// </summary>
        private Queue<int> frameCountHist = new Queue<int>();

        /// <summary>
        /// 开始计算
        /// </summary>
        public void Start()
        {
            this.stopwatch.Start();
        }

        /// <summary>
        /// 停止计算
        /// </summary>
        public void Stop()
        {
            this.stopwatch.Stop();
            this.frameCount = 0;
            this.frameCountHistTotal = 0;
            this.lastFrameTime = 0;
            this.frameCountHist.Clear();
        }

        /// <summary>
        /// 计算FPS
        /// </summary>
        public void CalcFps()
        {
            ++this.frameCount;
            if (this.stopwatch.ElapsedMilliseconds - this.lastFrameTime < 1000)
                return;

            this.frameCountHist.Enqueue(this.frameCount);
            this.frameCountHistTotal += this.frameCount;
            if (frameCountHist.Count > this.Duration)
            {
                frameCountHistTotal -= frameCountHist.Dequeue();
            }

            this.FPS = frameCountHistTotal / frameCountHist.Count;

            this.frameCount = 0;
            this.lastFrameTime = this.stopwatch.ElapsedMilliseconds;
        }

        /// <summary>
        /// 销毁
        /// </summary>
        public void Dispose()
        {
            this.Stop();
        }

        /// <summary>
        /// 销毁所有的辅助类
        /// </summary>
        public static void DisposeAll()
        {
            lock (allHelpers)
            {
                foreach (FPSHelper helper in allHelpers)
                {
                    helper.Dispose();
                }

                allHelpers.Clear();
            }
        }
    }
}
