#include "customgui_datetime.h"
#include "c4d_string.h"
#include "c4d_gui.h"


static DateTimechooserLib *lib_DateTime = NULL;

static DateTimechooserLib *CheckLib(LONG offset)
{
	return (DateTimechooserLib*)CheckLib(DATETIME_GUI, offset, (C4DLibrary**)&lib_DateTime);
}

#define DateTimeCall(b) 			DateTimechooserLib *lib = CheckLib(LIBOFFSET(DateTimechooserLib,b)); \
															if (!lib || !lib->b) return; \
															(((iDateTimeData*)this)->*lib->b)

#define DateTimeCallR(a,b) 		DateTimechooserLib *lib = CheckLib(LIBOFFSET(DateTimechooserLib,b)); \
															if (!lib || !lib->b) return a; \
															return (((iDateTimeData*)this)->*lib->b)

#define DateTimeGuiCall(b) 		DateTimechooserLib *lib = CheckLib(LIBOFFSET(DateTimechooserLib,b)); \
															if (!lib || !lib->b) return; \
															(((iDateTimeControl*)this)->*lib->b)

#define DateTimeGuiCallR(a,b) DateTimechooserLib *lib = CheckLib(LIBOFFSET(DateTimechooserLib,b)); \
															if (!lib || !lib->b) return a; \
															return (((iDateTimeControl*)this)->*lib->b)

tagDateTime DateTimeControl::GetDateTime() { DateTimeGuiCallR(tagDateTime(), GetDateTimeGUI)(); }
void DateTimeControl::SetDateTime(tagDateTime *d, Bool bSetDate, Bool bSetTime) { DateTimeGuiCall(SetDateTimeGUI)(d, bSetDate, bSetTime); }

tagDateTime DateTimeData::GetDateTime() { DateTimeCallR(tagDateTime(), GetDateTimeData)(); }
void DateTimeData::SetDateTime(tagDateTime *d, Bool bSetDate, Bool bSetTime) { DateTimeCall(SetDateTimeData)(d, bSetDate, bSetTime); }

LReal GetJulianDay(tagDateTime &t)
{
	DateTimechooserLib *lib = CheckLib(LIBOFFSET(DateTimechooserLib, GetJulianDay)); if (!lib || !lib->GetJulianDay) return -1;
	return lib->GetJulianDay(t);
}

tagDateTime FromJulianDay(LReal j)
{
	DateTimechooserLib *lib = CheckLib(LIBOFFSET(DateTimechooserLib, GetJulianDay)); if (!lib || !lib->GetJulianDay) return tagDateTime();
	return lib->FromJulianDay(j);
}

void DateTimeNow(tagDateTime& t)
{
	DateTimechooserLib *lib = CheckLib(LIBOFFSET(DateTimechooserLib, DateTimeNow)); if (!lib || !lib->DateTimeNow) return;
	lib->DateTimeNow(t);
}

Bool GetGMTime(const tagDateTime &tLocal, tagDateTime &tGMT)
{
  DateTimechooserLib *lib = CheckLib(LIBOFFSET(DateTimechooserLib, GetGMTime)); if (!lib || !lib->GetGMTime) { tGMT = tLocal; return FALSE; }
	return lib->GetGMTime(tLocal, tGMT);
}

Bool GetLocalTime(const tagDateTime &tGMT, tagDateTime &tLocal)
{
  DateTimechooserLib *lib = CheckLib(LIBOFFSET(DateTimechooserLib, GetLocalTime)); if (!lib || !lib->GetLocalTime) { tLocal = tGMT; return FALSE; }
	return lib->GetLocalTime(tGMT, tLocal);
}

LONG GetDayOfWeek(LONG lYear, LONG lMonth, LONG lDay)
{
	DateTimechooserLib *lib = CheckLib(LIBOFFSET(DateTimechooserLib, GetDayOfWeek)); if (!lib || !lib->GetDayOfWeek) return -1;
	return lib->GetDayOfWeek(lYear, lMonth, lDay);
}

String FormatTime(const char* pszFormat, tagDateTime &t)
{
	DateTimechooserLib *lib = CheckLib(LIBOFFSET(DateTimechooserLib, FormatTime)); if (!lib || !lib->FormatTime) return String();
	return lib->FormatTime(pszFormat, t);
}

DateTimeData* DateTimeData::Alloc()
{
  DateTimechooserLib *lib = CheckLib(LIBOFFSET(DateTimechooserLib, DateTimeData_Alloc)); if (!lib || !lib->DateTimeData_Alloc) return NULL;
	return lib->DateTimeData_Alloc();
}

void DateTimeData::Free(DateTimeData *&pData)
{
  DateTimechooserLib *lib = CheckLib(LIBOFFSET(DateTimechooserLib, DateTimeData_Free)); if (!lib || !lib->DateTimeData_Free) return;
	lib->DateTimeData_Free(pData);
}

LONG CompareDateTime(const tagDateTime &a, const tagDateTime &b)
{
	LONG c;
	c = a.lYear - b.lYear;
	if (c != 0) return c;
	c = a.lMonth - b.lMonth;
	if (c != 0) return c;
	c = a.lDay - b.lDay;
	if (c != 0) return c;
	c = a.lHour - b.lHour;
	if (c != 0) return c;
	c = a.lMinute - b.lMinute;
	if (c != 0) return c;
	c = a.lSecond - b.lSecond;
	return c;
}

Bool tagDateTime::operator == (const tagDateTime& b) const
{
  return CompareDateTime(*this, b) == 0;
}

Bool tagDateTime::operator != (const tagDateTime& b) const 
{ 
  return CompareDateTime(*this, b) != 0;
}

Bool tagDateTime::operator <= (const tagDateTime &b) const
{
  return CompareDateTime(*this, b) <= 0;
}

Bool tagDateTime::operator < (const tagDateTime &b) const
{
  return CompareDateTime(*this, b) < 0;
}

Bool tagDateTime::operator >= (const tagDateTime &b) const
{
  return CompareDateTime(*this, b) >= 0;
}

Bool tagDateTime::operator > (const tagDateTime &b) const
{
  return CompareDateTime(*this, b) > 0;
}

