text: ﻿using Sandbox.Game.Debugging;
  using Sandbox.Game.World;
  
  namespace Sandbox.Engine.Utils
  {
      public static class MyFpsManager
      {
          static long m_lastTime = 0;
          static uint m_fpsCounter = 0;
          static uint m_sessionTotalFrames = 0;
          static uint m_maxSessionFPS = 0;
          static uint m_minSessionFPS = int.MaxValue;
  
          static uint m_lastFpsDrawn = 0;
  
          static long m_lastFrameTime = 0;
          static long m_lastFrameMin = long.MaxValue;
          static long m_lastFrameMax = long.MinValue;
          static byte m_firstFrames = 0;
  
          //  Returns FPS once per second. We can't display actual FPS at every frame, because it will be changing quickly and so unreadable.
          public static int GetFps()
          {
              return (int)m_lastFpsDrawn;
          }
  
          public static int GetSessionTotalFrames()
          {
              return (int)m_sessionTotalFrames;
          }
  
          public static int GetMaxSessionFPS()
          {
              return (int)m_maxSessionFPS;
          }
  
          public static int GetMinSessionFPS()
          {
              return (int)m_minSessionFPS;
          }
  
          /// <summary>
          /// Returns update + render time of last frame in ms
          /// </summary>
          /// <returns></returns>
          public static float FrameTime { get; private set; }
  
          /// <summary>
          /// Returns update + render time of last frame (Average in last second)
          /// </summary>
          /// <returns></returns>
          public static float FrameTimeAvg { get; private set; }
          public static float FrameTimeMin { get; private set; }
          public static float FrameTimeMax { get; private set; }
  
          public static void Update()
          {
              m_fpsCounter++;
              m_sessionTotalFrames++;
  
              if (MySession.Static == null)
              {
                  m_sessionTotalFrames = 0;
                  m_maxSessionFPS = 0;
                  m_minSessionFPS = int.MaxValue;
              }
  
              long frameTicks = MyPerformanceCounter.ElapsedTicks - m_lastFrameTime;
              FrameTime = (float)MyPerformanceCounter.TicksToMs(frameTicks);
              m_lastFrameTime = MyPerformanceCounter.ElapsedTicks;
  
              if (frameTicks > m_lastFrameMax)
              {
                  m_lastFrameMax = frameTicks;
              }
  
              if (frameTicks < m_lastFrameMin)
              {
                  m_lastFrameMin = frameTicks;
              }
  
              long ticksFromLastDraw = MyPerformanceCounter.ElapsedTicks - m_lastTime;
              float msFromLastDraw = (float)MyPerformanceCounter.TicksToMs(ticksFromLastDraw);
  
              if (msFromLastDraw >= 1000)
              {
                  FrameTimeMin = (float)MyPerformanceCounter.TicksToMs(m_lastFrameMin);
                  FrameTimeMax = (float)MyPerformanceCounter.TicksToMs(m_lastFrameMax);
                  FrameTimeAvg = msFromLastDraw / m_fpsCounter;
                  m_lastFrameMin = long.MaxValue;
                  m_lastFrameMax = long.MinValue;
  
                  if (MySession.Static != null && m_firstFrames > 20)
                  {
                      m_minSessionFPS = System.Math.Min(m_minSessionFPS, m_fpsCounter);
                      m_maxSessionFPS = System.Math.Max(m_maxSessionFPS, m_fpsCounter);
                  }
                  if (m_firstFrames <= 20) m_firstFrames++;
  
                  m_lastTime = MyPerformanceCounter.ElapsedTicks;
                  m_lastFpsDrawn = m_fpsCounter;
                  m_fpsCounter = 0;
              }
          }
  
          public static void Reset()
          {
              m_maxSessionFPS = 0;
              m_minSessionFPS = int.MaxValue;
              m_fpsCounter = 0;
              m_sessionTotalFrames = 0;
              m_lastTime = MyPerformanceCounter.ElapsedTicks;
              m_firstFrames = 0;
          }
  
          public static void PrepareMinMax()
          {
              if (m_firstFrames <= 20)
              {
                  m_minSessionFPS = m_lastFpsDrawn;
                  m_maxSessionFPS = m_lastFpsDrawn;
              }
          }
      }
  }
  