//--------------------------------------------------------------------
// Environment section
//--------------------------------------------------------------------
#define DAY_TIME_NIGHT		"Night"
#define DAY_TIME_MORNING	"Morning"
#define DAY_TIME_DAY		"Day"
#define DAY_TIME_EVENING	"Evening"

float  GetTime(){ return stf(Environment.time); }
float  GetHour(){ return stf(Environment.date.hour); }
float  GetMinute(){ return stf(Environment.date.min); }
float  GetSecond(){ return stf(Environment.date.sec); }
int	GetDataYear(){ return sti(Environment.date.year); }
int	GetDataMonth(){ return sti(Environment.date.month); }
int	GetDataDay(){ return sti(Environment.date.day); }

void SetDayTime(string name)
{
	switch(name)
	{
	case DAY_TIME_NIGHT:	SetCurrentTime(5,59);	break;
	case DAY_TIME_MORNING:	SetCurrentTime(9,59);	break;
	case DAY_TIME_DAY:		SetCurrentTime(17,59);	break;
	case DAY_TIME_EVENING:	SetCurrentTime(21,59);	break;
	}
}

string GetDayTime()
{
	if(GetTime()<6.0) return DAY_TIME_NIGHT;
	if(GetTime()<10.0) return DAY_TIME_MORNING;
	if(GetTime()<18.0) return DAY_TIME_DAY;
	if(GetTime()<22.0) return DAY_TIME_EVENING;
	return DAY_TIME_NIGHT;
}
bool IsDay()
{
// LDH fix for day changing back to night for an hour in the mornings
//	if(GetTime() > 7.0)	{if(GetTime() < 22.0) return true; } return false;
	float fTime = GetTime();
	if(fTime > 6.0 && fTime < 22.0) return true;
	return false;
}

// KK: and what with a LEAP years?! -->
int GetMonthDays(int month, int year)
{
	while(month>12) {month -= 12;}
	switch(month)
	{
	case 1:		return 31;	break;
	case 2:
		bool isLeap = false;
		if (year % 400.0 == 0.0) {
			isLeap = true;
		} else {
			if (year % 100.0 != 0.0) {
				if (year % 4.0 == 0.0) isLeap = true;
			}
		}
		if (!isLeap)
			return 28;
		else
			return 29;
		break;
	case 3:		return 31;	break;
	case 4:		return 30;	break;
	case 5:		return 31;	break;
	case 6:		return 30;	break;
	case 7:		return 31;	break;
	case 8:		return 31;	break;
	case 9:		return 30;	break;
	case 10:	return 31;	break;
	case 11:	return 30;	break;
	case 12:	return 31;	break;
	}
	Trace("Error: " + month + " month is not relevant");
	return 30;
}
// <-- KK
int GetAddingDataYear(int addYear,int addMonth,int addDay)
{
	int nextDay = GetDataDay()+addDay;
	int curMonth = GetDataMonth();
	int curYear = GetDataYear(); // KK
	while(GetMonthDays(curMonth, curYear)<nextDay) // KK
	{
		nextDay = nextDay - GetMonthDays(curMonth, curYear); // KK
		curMonth++;
	}
	int nextMonth = curMonth+addMonth;
	int nextYear = curYear+addYear; // KK
	while(12<nextMonth)
	{
		nextMonth = nextMonth - 12;
		nextYear++;
	}
	return nextYear;
}
int GetAddingDataMonth(int addYear,int addMonth,int addDay)
{
	int nextDay = GetDataDay()+addDay;
	int curMonth = GetDataMonth();
	int curYear = GetDataYear(); // KK
	while(GetMonthDays(curMonth, curYear)<nextDay) // KK
	{
		nextDay = nextDay - GetMonthDays(curMonth, curYear); // KK
		curMonth++;
	}
	int nextMonth = curMonth+addMonth;
	while(12<nextMonth)
	{
		nextMonth = nextMonth - 12;
	}
	return nextMonth;
}
int GetAddingDataDay(int addYear,int addMonth,int addDay)
{
	int nextDay = GetDataDay()+addDay;
	int curMonth = GetDataMonth();
	int curYear = GetDataYear(); // KK
	while(GetMonthDays(curMonth, curYear)<nextDay) // KK
	{
		nextDay = nextDay - GetMonthDays(curMonth, curYear); // KK
		curMonth++;
	}
	return nextDay;
}
int GetAddingTimeDay(int hour,int minute)
{
	float curtime = GetTime();
	float nexttime = curtime+hour+(makefloat(minute)/60.0);
	int addingDays = 0;
	while(nexttime>=24.0)
	{
		nexttime = nexttime - 24.0;
		addingDays++;
	}
	return addingDays;
}
void AddTimeToCurrent(int hour,int minute)
{
	float curtime = GetTime();
	float nexttime = curtime+hour+(makefloat(minute)/60.0);
	int addingDays = 0;
	while(nexttime>=24.0)
	{
		nexttime = nexttime - 24.0;
		addingDays++;
	}
	AddDataToCurrent(0,0,addingDays, true); // do each day's update
	//this is handled by AddData below NK 05-04-17 if(addingDays>0) PostEvent("NextDay",0);
	Environment.time = nexttime;
	Environment.date.hour = makeint(nexttime);
	worldMap.date.hour = makeint(nexttime);
	nexttime = (nexttime - stf(Environment.date.hour))*60.0;
	Environment.date.min = makeint(nexttime);
	worldMap.date.min = makeint(nexttime);
}
void AddDataToCurrent(int addYear,int addMonth,int addDay, bool doupdate)
{
	if(addYear == 0 && addMonth == 0 && addDay == 0) return; // NK 05-04-24
	int oldDay = GetDataDay(); int oldMonth = GetDataMonth(); int oldYear = GetDataYear(); // NK 05-04-17 for total days tracking
	int nextDay = GetDataDay()+addDay;
	int curMonth = GetDataMonth();
	int curYear = GetDataYear(); // KK
	while(GetMonthDays(curMonth, curYear)<nextDay) // KK
	{
		nextDay = nextDay - GetMonthDays(curMonth, curYear); // KK
		curMonth++;
	}
	int nextMonth = curMonth+addMonth;
	int nextYear = curYear+addYear; // KK
	while(12<nextMonth)
	{
		nextMonth = nextMonth - 12;
		nextYear++;
	}
	if(addYear!=0 || addMonth!=0 || addDay!=0)	// NK 05-04-17 do this once per day: PostEvent("NextDay",0);
	{
		if(doupdate)
		{
			int totaldays = GetPastTime("day", oldYear, oldMonth, oldDay, 0, nextYear, nextMonth, nextDay, 0);
			int i;
			// WM -->
			int start = 0;
			/*if(CheckAttribute(wdmgrid,"lastupdate.start"))
			{
				start = sti(wdmgrid.lastupdate.start);
			}*/
			for(i = 0; i < totaldays; i++)
			{
				//Event("NextDay");
				DoDailyUpdates("all"); // 05-05-04
				AddDataToCurrent(0,0,1,false); // update the date
			}
			//for(i = 0; i < totaldays; i++) PostEvent("NextDay",0);
			// WM <--
		}
		else
		{
			Environment.date.year = nextYear;
			Environment.date.month = nextMonth;
			Environment.date.day = nextDay;
			worldMap.date.year = nextYear;
			worldMap.date.month = nextMonth;
			worldMap.date.day = nextDay;
		}
	}
	// NK <--
}

// NK 05-05-04
// mask is a bitmask for: repair/dcu/towns/itrade/berthing/stores/fleets/quests. Length is 8 chars.
// can also be set to "all" to do all.
void DoDailyUpdates(string mask)
{
	if(mask == "all")
	{
		//trace("Gauging: Start DU");
		ProcessDayRepair();
		DailyCrewUpdate();
		UpdateAllTowns(false);
		UpdateAllItemTraders(false);
		DailyShipBerthingUpdate();
		//trace("Gauging: Stores start");
		UpdateAllStores(false);
		//trace("Gauging: Stores end");
		//wdmFleetsUpdateDay(); //wdmFleetsUpdate(false, false);
		QuestsCheck();
		//trace("Gauging: end DU");
	}
	else
	{
		if(getsymbol(mask, 0) == "1") ProcessDayRepair();
		if(getsymbol(mask, 1) == "1") DailyCrewUpdate();
		if(getsymbol(mask, 2) == "1") UpdateAllTowns(false);
		if(getsymbol(mask, 3) == "1") UpdateAllItemTraders(false);
		if(getsymbol(mask, 4) == "1") DailyShipBerthingUpdate();
		if(getsymbol(mask, 5) == "1") UpdateAllStores(false);
		//if(getsymbol(mask, 6) == "1") wdmFleetsUpdateDay(); //wdmFleetsUpdate(false, false);
		//if(getsymbol(mask, 7) == "1") QuestsCheck();
		if(getsymbol(mask, 6) == "1" || getsymbol(mask, 7) == "1") QuestsCheck();
	}
	AllDaysCount++;//MAXIMUS: for daily skills update
}
// NK <--
// "year","month","day","hour","minute"
int GetPastTime(string timeUnit,
				int pastYear,int pastMonth,int pastDay, float pastTime,
				int currentYear,int currentMonth,int currentDay, float currentTime)
{
	float dtime = currentTime - pastTime;
	int dyear = currentYear - pastYear;
	int dmonth = currentMonth - pastMonth;
	int dday = currentDay - pastDay;

	if(dtime<0.0)
	{
		dday--;
		dtime = dtime + 24.0;
	}
	if(dday<0)
	{
		dmonth--;
		if(pastMonth>1) dday = dday + GetMonthDays(pastMonth-1, pastYear); // KK
		else dday = dday + GetMonthDays(12, pastYear); // KK
	}
	if(dmonth<0)
	{
		dyear--;
		dmonth = dmonth+12;
	}

	if(dyear<0) return 0;
	if(timeUnit=="year") return dyear;

	if(timeUnit=="month")
	{
		return dmonth+dyear*12;
	}
	
	int dayCount = dday + dyear*365;
	for(int i=0; i<dmonth; i++)
	{
		dayCount = dayCount + GetMonthDays(pastMonth, pastYear); // KK
		pastMonth++;
		if(pastMonth>12) pastMonth = 1;
	}
	//if(timeUnit=="day")	return dayCount;

	if(timeUnit=="hour") return dayCount*24 + makeint(dtime);
	if(timeUnit=="minute") return dayCount*1440 + makeint(dtime*60.0);
	return dayCount;
}

void SetCurrentTime(int hour, int minutes)
{
	Environment.date.hour = makefloat(hour);
	Environment.date.min = makefloat(minutes);
	Environment.time = makefloat(hour) + makefloat(minutes)/60.0;
	worldMap.date.hour = makefloat(hour);
	worldMap.date.min = makefloat(minutes);
}

// NK add names 05-04-16 -->
string GetMonthName(int month)
{
	string tmpstr = "January";
	switch(month)
	{
		case 1:		tmpstr = "January";	break;
		case 2:		tmpstr = "February";	break;
		case 3:		tmpstr = "March";	break;
		case 4:		tmpstr = "April";	break;
		case 5:		tmpstr = "May";	break;
		case 6:		tmpstr = "June";	break;
		case 7:		tmpstr = "July";	break;
		case 8:		tmpstr = "August";	break;
		case 9:		tmpstr = "September";	break;
		case 10:	tmpstr = "October";	break;
		case 11:	tmpstr = "November";	break;
		case 12:	tmpstr = "December";	break;
		Trace("Error: " + month + " month is not relevant");
	}
	//return XI_ConvertString(tmpstr);
	return tmpstr;
}

string GetDayName(int weekday)
{
		string tmpstr = "Sunday";
	switch(weekday)
	{
		case 1:		tmpstr = "Sunday";	break;
		case 2:		tmpstr = "Monday";	break;
		case 3:		tmpstr = "Tuesday";	break;
		case 4:		tmpstr = "Wednesday";	break;
		case 5:		tmpstr = "Thursday";	break;
		case 6:		tmpstr = "Friday";	break;
		case 7:		tmpstr = "Saturday";	break;
	}
	//return XI_ConvertString(tmpstr);
	return tmpstr;
}

//note for now we do just Gregorian.
// taken from http://www.mcs.csuhayward.edu/~malek/Mathlinks/Weekdays.html
int GetWeekday(int day, int month, int year)
{
	int C = year / 100;
	int Y = year % 100;
	Y -= month<3;
	month -= 2;
	if(month <= 0) month = 12 - month;
	int wday = abs((day + makeint(2.6*makefloat(month) - 0.2) - 2 * C + Y + Y/4 + C/4) % 7);
	/*while(wday > 7) wday -= 7;
	while(wday < 1) wday += 7;*/
	return wday;
}
