#pragma once

#include "i18n.qh"

// ===============================================
//  Time processing and counting functions/macros
// ===============================================

#define count_years_decs(time, decs) sprintf(CTX(_("CI_DEC^%s years")), ftos_decimals(time, decs))
#define count_years(time) \
	count_fill(time, \
	_("CI_ZER^%d years"), /* zeroth */ \
	_("CI_FIR^%d year"),  /* first */ \
	_("CI_SEC^%d years"), /* year */ \
	_("CI_THI^%d years"), /* third */ \
	_("CI_MUL^%d years")) /* multi */

#define count_weeks_decs(time, decs) sprintf(CTX(_("CI_DEC^%s weeks")), ftos_decimals(time, decs))
#define count_weeks(time) \
	count_fill(time, \
	_("CI_ZER^%d weeks"), /* zeroth */ \
	_("CI_FIR^%d week"),  /* first */ \
	_("CI_SEC^%d weeks"), /* week */ \
	_("CI_THI^%d weeks"), /* third */ \
	_("CI_MUL^%d weeks")) /* multi */

#define count_days_decs(time, decs) sprintf(CTX(_("CI_DEC^%s days")), ftos_decimals(time, decs))
#define count_days(time) \
	count_fill(time, \
	_("CI_ZER^%d days"), /* zeroth */ \
	_("CI_FIR^%d day"),  /* first */ \
	_("CI_SEC^%d days"), /* day */ \
	_("CI_THI^%d days"), /* third */ \
	_("CI_MUL^%d days")) /* multi */

#define count_hours_decs(time, decs) sprintf(CTX(_("CI_DEC^%s hours")), ftos_decimals(time, decs))
#define count_hours(time) \
	count_fill(time, \
	_("CI_ZER^%d hours"), /* zeroth */ \
	_("CI_FIR^%d hour"),  /* first */ \
	_("CI_SEC^%d hours"), /* hour */ \
	_("CI_THI^%d hours"), /* third */ \
	_("CI_MUL^%d hours")) /* multi */


#define count_minutes_decs(time, decs) sprintf(CTX(_("CI_DEC^%s minutes")), ftos_decimals(time, decs))
#define count_minutes(time) \
	count_fill(time, \
	_("CI_ZER^%d minutes"), /* zeroth */ \
	_("CI_FIR^%d minute"),  /* first */ \
	_("CI_SEC^%d minutes"), /* minute */ \
	_("CI_THI^%d minutes"), /* third */ \
	_("CI_MUL^%d minutes")) /* multi */

#define count_seconds_decs(time, decs) sprintf(CTX(_("CI_DEC^%s seconds")), ftos_decimals(time, decs))
#define count_seconds(time) \
	count_fill(time, \
	_("CI_ZER^%d seconds"), /* zeroth */ \
	_("CI_FIR^%d second"),  /* first */ \
	_("CI_SEC^%d seconds"), /* second */ \
	_("CI_THI^%d seconds"), /* third */ \
	_("CI_MUL^%d seconds")) /* multi */

// returns 1st, 2nd, 3rd, nth ordinal number from a cardinal number (integer)
ERASEABLE
string count_ordinal(int interval)
{
	// This function is designed primarily for the English language, it's impossible
	// to accomodate all languages unless we do a specific function for each one...
	// and since that's not technically feasible/practical, this is all we've got folks.

	int last2digits = interval % 100;

	// numbers ending with 11, 12 and 13 don't follow the standard pattern
	if (last2digits < 4 || last2digits > 20)
		switch (last2digits % 10)
		{
			case 1: return sprintf(_("%dst"), interval);
			case 2: return sprintf(_("%dnd"), interval);
			case 3: return sprintf(_("%drd"), interval);
		}

	return sprintf(_("%dth"), interval);
}

ERASEABLE
string count_fill(float interval, string zeroth, string first, string second, string third, string multi)
{
	// This function is designed primarily for the English language, it's impossible
	// to accomodate all languages unless we do a specific function for each one...
	// and since that's not technically feasible/practical, this is all we've got folks.

	// Here you can insert specific strings based on the interval number, so you could do
	// i.e. count_seconds which outputs like this:
	//   0 seconds
	//   1 second
	//   2 seconds
	//   3 seconds
	//   etc... minutes, hours, days, etc.

	switch (floor(interval))
	{
		case 0: return sprintf(CTX(zeroth), interval);
		case 1:
			if (interval == 1) // EXACTLY value of 1
				return sprintf(CTX(first), interval);
			else
				return sprintf(CTX(multi), interval);
		case 2: return sprintf(CTX(second), interval);
		case 3: return sprintf(CTX(third), interval);
		default: return sprintf(CTX(multi), interval);
	}
	return "";
}

ERASEABLE
string process_time(float outputtype, int seconds)
{
	int tmp_hours = 0, tmp_minutes = 0, tmp_seconds;
	int tmp_years = 0, tmp_weeks = 0, tmp_days = 0;

	tmp_seconds = floor(seconds);

	if (tmp_seconds)
	{
		tmp_minutes = floor(tmp_seconds / 60);

		if (tmp_minutes)
		{
			tmp_seconds -= tmp_minutes * 60;
			tmp_hours = floor(tmp_minutes / 60);

			if (tmp_hours)
			{
				tmp_minutes -= tmp_hours * 60;
				tmp_days = floor(tmp_hours / 24);

				if (tmp_days)
				{
					tmp_hours -= tmp_days * 24;
					tmp_weeks = floor(tmp_days / 7);

					if (tmp_weeks)
					{
						tmp_days -= tmp_weeks * 7;
						tmp_years = floor(tmp_weeks / 52);
					}
				}
			}
		}
	}

	switch (outputtype)
	{
		case 1: return sprintf("%02d:%02d:%02d", tmp_hours, tmp_minutes, tmp_seconds);
		case 2:
		{
			string output = "";
			#define APPEND_TIME(unit) \
				if (tmp_##unit) \
					output = strcat(output, ((output != "") ? ", " : ""), count_##unit(tmp_##unit))
			APPEND_TIME(years);
			APPEND_TIME(weeks);
			APPEND_TIME(days);
			APPEND_TIME(hours);
			APPEND_TIME(minutes);
			APPEND_TIME(seconds);
			#undef APPEND_TIME
			if (output == "")
				return count_seconds(0);
			return output;
		}
		case 3:
		{
			string output = count_hours(tmp_hours);

			if (tmp_weeks)
				tmp_days += (tmp_weeks * 7);
			if (tmp_years)
				tmp_days += (tmp_years * 365);
			if (tmp_days)
				output = sprintf(
					count_days(tmp_days),
					((output != "") ? strcat(", ", output) : "")
				);

			return output;
		}
	}
	return "";
}
