// --------------------------------------------------------------------------
// Citadel: TimeDate.CPP
//
// Routines relating to the time and date

#include "ctdl.h"
#pragma hdrstop

// --------------------------------------------------------------------------
// Contents
//
// dayofweek()				returns current day of week 0 - 6; sun = 0
// diffstamp()				display the diffrence from timestamp to present
// getdstamp()				get datestamp (text format)
// gettstamp()				get timestamp (text format)
// hour()					returns hour of day 0 - 23
// pause()					busy-waits N/100 seconds
// CheckIdleUserTimeout()	returns TRUE if time has been exceeded


// this is the number of seconds MSC 7.00 is off by
#define TIME_FUDGE 2209075200L

Bool TimeoutChecking;


// --------------------------------------------------------------------------
// dayofweek(): Returns current day of week 0 - 6; sun = 0.

int dayofweek(void)
	{
	long stamp;
	struct tm *timestruct;

	time(&stamp);

	timestruct = localtime(&stamp);

	return (timestruct->tm_wday);
	}


// --------------------------------------------------------------------------
// diffstamp(): Display the diffrence from timestamp to present.

const char *diffstamp(time_t oldtime)
	{
	time_t diff;

	diff = time(NULL) - oldtime;

	// break it down
	long days;						// long in case it has been 90 years. :)
	int hours, minutes, seconds;

	seconds = (int) (diff % 60L);
	diff /= 60L;
	minutes = (int) (diff % 60L);
	diff /= 60L;
	hours = (int) (diff % 24L);
	days = diff / 24L;


	if (days)
		{
		sprintf(TI()diffstampstr, getmsg(1006), ltoac(days),
			(days == 1L) ? ns : justs, hours, minutes, seconds);
		}
	else
		{
		sprintf(TI()diffstampstr, getmsg(420), hours, minutes, seconds);
		}

	return (TI()diffstampstr);
	}


// --------------------------------------------------------------------------
// getdstamp(): Get datestamp (text format).

void getdstamp(char *buffer, uint stamp)
	{
	char month[4];

	const int year = (((stamp >> 9) & 0x7f) + 80) % 100;
	const int mth = (stamp >> 5) & 0x0f;
	const int day = stamp & 0x1f;

	if (mth < 1 || mth > 12 || day < 1 || day > 31)
		{
		strcpy(buffer, getmsg(1474));
		return;
		}

	strcpy(month, monthTab[mth-1]);

	sprintf(buffer, getmsg(1475), year, month, day);
	}


// --------------------------------------------------------------------------
// gettstamp(): get timestamp (text format)

void gettstamp(char *buffer, uint stamp)
	{
	int hours, minutes, seconds;

	hours = (stamp >> 11) & 0x1f;
	minutes = (stamp >> 5) & 0x3f;
	seconds = (stamp & 0x1f) * 2;

	sprintf(buffer, getmsg(1476), hours, minutes, seconds);
	}


// --------------------------------------------------------------------------
// hour(): returns hour of day (0 - 23)

int hour(void)
	{
	long stamp;
	struct tm *timestruct;

	time(&stamp);

	timestruct = localtime(&stamp);

	return (timestruct->tm_hour);
	}


// --------------------------------------------------------------------------
// pause(): Waits N/100 seconds.

void pause(register int ptime)
	{
	union REGS in, out;
	register int i, j = 0;

	in.h.ah = 0x2C;
	intdos(&in, &out);
	i = out.h.dl;

	while (j < ptime)
		{
		in.h.ah = 0x2C;
		intdos(&in, &out);

		if (out.h.dl < (uchar) i)
			{
			j += (100 + out.h.dl) - i;
			}
		else
			{
			j += out.h.dl - i;
			}

		i = out.h.dl;

		CitIsIdle();
		}
	}


// --------------------------------------------------------------------------
// netpause(): waits N/100 seconds.

void netpause(register int ptime)
	{
	union REGS in, out;
	register int i, j=0;
	int ch;

	in.h.ah = 0x2C;
	intdos(&in, &out);
	i = out.h.dl;

	while (j < ptime)
		{
		in.h.ah=0x2C;
		intdos(&in, &out);

		if (out.h.dl < (uchar)i)
			{
			j += (100 + out.h.dl) - i;
			}
		else
			{
			j += out.h.dl - i;
			}

		i = out.h.dl;

		if (TI()SerialPort.IsInputReady())
			{
			ch = TI()SerialPort.Input();

			if (debug)
				{
				outCon(ch);
				}
			}

		CitIsIdle();
		}
	}


// --------------------------------------------------------------------------
// twirlypause(): waits N/100 seconds.

void twirlypause(register int ptime)
	{
	union REGS in, out;
	register int i, j=0;

	in.h.ah = 0x2C;
	intdos(&in, &out);
	i = out.h.dl;

	while (j < ptime && !KBReady() && !(TI()SerialPort.IsInputReady() && SerialPort.HaveCarrier() &&
			TI()modStat && (TI()whichIO == MODEM)))
		{
		in.h.ah = 0x2C;
		intdos(&in, &out);

		if (out.h.dl < (uchar) i)
			{
			j += (100 + out.h.dl) - i;
			}
		else
			{
			j += out.h.dl - i;
			}
		i = out.h.dl;

		CitIsIdle();
		}
	}


// --------------------------------------------------------------------------
// CheckIdleUserTimeout(): returns TRUE if time has been exceeded.

Bool CheckIdleUserTimeout(Bool InOutput)
	{
	if (!TimeoutChecking)
		{
		return (FALSE);
		}

	int Timeout = TI()loggedIn ?
			(onConsole ? cfg.consoletimeout : cfg.timeout) :
			cfg.unlogtimeout;

	if (InOutput)
		{
		Timeout = max(cfg.OutputTimeout, Timeout);
		}

	return (TI()sleepkey ||
			(((time(NULL) - TI()LastActiveTime) / 60) >= Timeout));
	}


#ifdef MSC
#undef time
time_t CitadelTime(time_t *tloc)
	{
	time_t x;

	x = time(NULL);

	if (tloc)
		{
		*tloc = x - TIME_FUDGE;
		}

	return (x - TIME_FUDGE);
	}
#endif
