/// ****************************************************************************
/// @file   
/// @author Dr.Neeton
/// @date   200X/X/X - 2014/01/24
/// 
/// @brief  Windowsの基本的なやつら？
/// 
/// ****************************************************************************

#pragma once

#include "CPL_WIN_Base.h"

namespace CPL {
namespace WIN {


// _____________________________________________________________________________
/// @brief 64bitタイムカウンター（粒度:ms）
///
/// 構築した時からの経過時間を管理する。\n
/// ※ Version 2.2.1より、Core::TimeCounterが実装されたため、そちら推奨。
// *****************************************************************************
class TimeCounter {
  U64         time_start;
  U64 mutable time_base;
  U64 mutable time_offs;

public:
  TimeCounter()
    : time_start( timeGetTime() )
    , time_base( time_start )
    , time_offs( 0 )
  {}

  U64 GetTime() const
  {
    U64 time_now = timeGetTime() + time_offs;
    if( time_now < time_base )
    {
      time_offs += 0x100000000L;
      time_base += 0x100000000L;
      time_now  += 0x100000000L;
    }
    return time_now - time_start;
  }

  void Reset()
  {
    time_start =
    time_base  = timeGetTime();
    time_offs  = 0;
  }
};



// _____________________________________________________________________________
/// @brief タイマー管理クラス
///
// *****************************************************************************
class Timer
{
private:
  char m_time_buf[ sizeof(TimeCounter) ];
  U64  m_next_time;

  TimeCounter const& timecnt_() const
  {
    return *reinterpret_cast<TimeCounter const*>(m_time_buf);
  }

public:
  Timer()
    : m_next_time(0)
  {
    Start();
  }

  U64   GetTime() const { return timecnt_().GetTime(); }  // 経過時間を取得
  void  Start(){ new(m_time_buf) TimeCounter(); }    // タイマー構築
  void  SetNextTime( U64 wait ){ m_next_time = GetTime() + wait; }

  void  WaitFPS( DWORD m_fps )
  {
    int wait = int(m_next_time - GetTime());
    if( wait > 0 ) Sleep( wait );
    m_next_time += 1000/m_fps;
  }

  // 指定時間を過ぎているか取得
  bool  GetNext() const
  {
    if( m_next_time <= GetTime() )
    {
      return true;
    }
    return false;
  }
};



} // namespace WIN
} // namespace CPL
