/*
								+----------------------------------+
								|                                  |
								|  ***  Long time-span timer  ***  |
								|                                  |
								|   Copyright © -tHE SWINe- 2008   |
								|                                  |
								|           LongTimer.h            |
								|                                  |
								+----------------------------------+
*/

#pragma once
#ifndef __LONG_TIMER_INCLUDED
#define __LONG_TIMER_INCLUDED

/**
 *	@file LongTimer.h
 *	@author -tHE SWINe-
 *	@date 2008
 *	@brief long period timer
 *
 *	@date 2012-06-19
 *
 *	Moved multiple inclusion guard before file documentation comment.
 *
 */

#include "Timer.h"

/**
 *	@brief counter with extremely long period (INT_MAX + 1 years)
 *
 *	Counts time as:
 *		- seconds + minutes + hours + days + weeks + months + years
 *		- seconds + minutes + hours + month-days + months + years
 *		- seconds + minutes + hours + year-days + years
 *
 *	@note Month is normalized to be 30 days here.
 */
class CLongTimer {
protected:
	static const int n_counter_num; // 4
	static const int p_counter_mod_list[4];
	mutable int p_counter_list[4];
	mutable double f_add_seconds;
	mutable CTimer timer;
	float m_f_speed;

public:
	/**
	 *	@brief default constructor; resets all counters
	 */
	CLongTimer();

	/**
	 *	@brief resets all counters
	 */
	void ResetTimer();

	/**
	 *	@brief gets relative timer speed
	 *
	 *	@return Returns timer speed (default 1).
	 */
	float f_Speed() const;

	/**
	 *	@brief sets relative timer speed
	 *
	 *	This makes it possible to create timers, running slower or faster than real-time.
	 *
	 *	@param[in] f_speed is timer speed ratio (must not be negative)
	 */
	void Set_Speed(float f_speed);

	/**
	 *	@brief updates timer counters
	 *
	 *	@return Returns true on success, false on failure (year counter overflow,
	 *		  it would take INT_MAX + 1 years).
	 *
	 *	@note This should be called from time to time (minute basis to hour basis)
	 *		so internal timer (counting seconds in double) wouldn't lose precission.
	 */
	bool TimeSample() const;

	/**
	 *	@brief gets seconds elapsed
	 *
	 *	@return Returns seconds part.
	 *
	 *	@note This may actually return numbers greater than 60, if called long since
	 *		last call to TimeSample().
	 *	@note This refers to time elapsed between last ResetTimer() and last TimeSample().
	 *	@note This doesn't invoke TimeSample(), it returns time after it's last invokation.
	 */
	double f_Seconds() const;

	/**
	 *	@brief gets minutes elapsed
	 *
	 *	@return Returns minutes part.
	 *
	 *	@note This refers to time elapsed between last ResetTimer() and last TimeSample().
	 *	@note This doesn't invoke TimeSample(), it returns time after it's last invokation.
	 */
	int n_Minutes() const;

	/**
	 *	@brief gets hours elapsed
	 *
	 *	@return Returns hours part.
	 *
	 *	@note This refers to time elapsed between last ResetTimer() and last TimeSample().
	 *	@note This doesn't invoke TimeSample(), it returns time after it's last invokation.
	 */
	int n_Hours() const;

	/**
	 *	@brief gets days in week
	 *
	 *	@return Returns days in week (0 - 6) part.
	 *
	 *	@note This refers to time elapsed between last ResetTimer() and last TimeSample().
	 *	@note This doesn't invoke TimeSample(), it returns time after it's last invokation.
	 */
	int n_Days() const;

	/**
	 *	@brief gets days in month
	 *
	 *	@return Returns days in month (0 - 29) part.
	 *
	 *	@note When using month days, time is seconds + minutes + hours +
	 *		month-days + months + years (weeks are not counted).
	 *	@note This refers to time elapsed between last ResetTimer() and last TimeSample().
	 *	@note This doesn't invoke TimeSample(), it returns time after it's last invokation.
	 */
	int n_DaysMonth() const;

	/**
	 *	@brief gets days in year
	 *
	 *	@return Returns days in year (0 - 364) part.
	 *
	 *	@note When using year days, time is seconds + minutes +
	 *		hours + year-days + years (weeks and months are not counted).
	 *	@note This refers to time elapsed between last ResetTimer() and last TimeSample().
	 *	@note This doesn't invoke TimeSample(), it returns time after it's last invokation.
	 */
	int n_DaysYear() const;

	/**
	 *	@brief gets weeks in month part
	 *
	 *	@return Returns weeks part (0 - 4; month is 4 weeks + 2 days).
	 *
	 *	@note This refers to time elapsed between last ResetTimer() and last TimeSample().
	 *	@note This doesn't invoke TimeSample(), it returns time after it's last invokation.
	 */
	int n_Weeks() const;

	/**
	 *	@brief gets months in year part
	 *
	 *	@return Returns months part (0 - 12; year is 12 months + 5 days).
	 *
	 *	@note Month is normalized to be 30 days here.
	 *	@note This refers to time elapsed between last ResetTimer() and last TimeSample().
	 *	@note This doesn't invoke TimeSample(), it returns time after it's last invokation.
	 */
	int n_Months() const;

	/**
	 *	@brief gets years part
	 *
	 *	@return Returns years part.
	 *
	 *	@note This refers to time elapsed between last ResetTimer() and last TimeSample().
	 *	@note This doesn't invoke TimeSample(), it returns time after it's last invokation.
	 */
	int n_Years() const;
};

#endif // !__LONG_TIMER_INCLUDED
