#include "blitz/misc/Time.h"

#include <algorithm>
#include <chrono>

namespace blitz {
namespace utils {

void AutoTimer::Update() {
	m_InternalTime += GetTime() - m_LastTime;
	if (m_InternalTime >= m_Interval) {
		if (m_Function != nullptr)
			m_Function();
		m_InternalTime %= m_Interval;
	}
	m_LastTime = GetTime();
}

void AutoTimer::Update(std::uint64_t delta) {
	m_InternalTime += delta;
	if (m_InternalTime >= m_Interval) {
		if (m_Function != nullptr)
			m_Function();
		m_InternalTime %= m_Interval;
	}
	m_LastTime = GetTime();
}

void AutoTimer::Reset() {
	m_InternalTime = 0;
	m_LastTime = GetTime();
}

bool Timer::Update(std::uint64_t delta) {
	m_InternalTime += delta;
	if (m_InternalTime >= m_Interval) {
		m_InternalTime %= m_Interval;
		return true;
	}
	return false;
}

void Timer::Reset() {
	m_InternalTime = 0;	 // let the timer active once at the beginning
}

bool CooldownTimer::Update(std::uint64_t delta) {
	if (m_Cooldown > 0) {
		m_Cooldown = static_cast<std::uint64_t>(std::max(static_cast<std::int64_t>(0), static_cast<std::int64_t>(m_Cooldown - delta)));
	}
	return m_Cooldown == 0;
}

void CooldownTimer::Reset() {
	m_Cooldown = 0;	 // let the timer active once at the beginning
}

void CooldownTimer::ApplyCooldown() {
	m_Cooldown = m_CooldownTime;
}

std::uint64_t GetTime() {
	return static_cast<std::uint64_t>(
		std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock().now().time_since_epoch()).count());
}

}  // namespace utils
}  // namespace blitz
