

//_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
//_/_/
//_/_/  This file is part of CMSDK version 2.0.0.170915_Beta4 (15 September 2017)
//_/_/  
//_/_/  developed by
//_/_/  
//_/_/  Communicative Machines Ltd. 
//_/_/    http://cmlabs.com/
//_/_/  Copyright (c) 2017
//_/_/  
//_/_/  in collaboration with 
//_/_/  
//_/_/  Icelandic Institute for Intelligent Machines ses
//_/_/    Menntavegur 1
//_/_/    101 Reykjavik
//_/_/    ICELAND
//_/_/    http://www.iiim.is/
//_/_/
//_/_/  and is released under the following
//_/_/  
//_/_/  EXTENDED BSD License
//_/_/
//_/_/  Redistribution and use in source and binary forms, with or without
//_/_/  modification, is permitted provided that the following conditions 
//_/_/  are met:
//_/_/
//_/_/  - Redistributions of source code must retain the above copyright 
//_/_/    and collaboration notice, this list of conditions and the following 
//_/_/    disclaimer.
//_/_/
//_/_/  - Redistributions in binary form must reproduce the above copyright 
//_/_/    notice, this list of conditions and the following disclaimer in the 
//_/_/    documentation and/or other materials provided with the distribution.
//_/_/
//_/_/  - Neither the name of its copyright holders nor the names of its 
//_/_/    contributors may be used to endorse or promote products derived from 
//_/_/    this software without specific prior written permission.
//_/_/
//_/_/  - CADIA Clause: The license granted in and to the software under this 
//_/_/    agreement is a limited-use license. The software may not be used in 
//_/_/    furtherance of: (i) intentionally causing bodily injury or severe 
//_/_/    emotional harm to any person; (ii) invading the personal privacy or 
//_/_/    violating the human rights of any person; or (iii) committing or 
//_/_/    preparing for any act of war. 
//_/_/
//_/_/  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
//_/_/  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
//_/_/  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 
//_/_/  PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 
//_/_/  OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
//_/_/  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
//_/_/  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
//_/_/  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
//_/_/  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
//_/_/  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
//_/_/  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//_/_/
//_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
#if !defined(_PSYTIME_H_)
#define _PSYTIME_H_

//#include "MemoryManager.h"
#include "Types.h"
#include "sys/timeb.h"

namespace cmlabs {

#define USEC_YEAR_0_TO_1970 62167305600000000L
#define SECS_PER_YEAR 31536000
#define SECS_PER_MONTH 2629744
#define SECS_PER_WEEK 604800
#define SECS_PER_DAY 86400
#define SECS_PER_HOUR 3600
#define SECS_PER_MIN 60
#define TIME_YEAR_1970 62167305600000000L

#define SECOND_MS	1000
#define MINUTE_MS	SECS_PER_MIN * 1000
#define HOUR_MS		SECS_PER_HOUR * 1000
#define DAY_MS		SECS_PER_DAY * 1000
#define WEEK_MS		SECS_PER_WEEK * 1000
#define MONTH_MS	SECS_PER_MONTH * 1000
#define YEAR_MS		(uint64)SECS_PER_YEAR * 1000

#define SECOND_US	(uint64)1000000
#define MINUTE_US	(uint64)SECS_PER_MIN * 1000000
#define HOUR_US		(uint64)SECS_PER_HOUR * 1000000
#define DAY_US		(uint64)SECS_PER_DAY * 1000000
#define WEEK_US		(uint64)SECS_PER_WEEK * 1000000
#define MONTH_US	(uint64)SECS_PER_MONTH * 1000000
#define YEAR_US		(uint64)SECS_PER_YEAR * 1000000

#define PSYSECOND	SECOND_US
#define PSYMINUTE	MINUTE_US
#define PSYHOUR		HOUR_US
#define PSYDAY		DAY_US
#define PSYWEEK		WEEK_US
#define PSYMONTH	MONTH_US
#define PSYYEAR		YEAR_US

static char PsyDays[][5] = {"None", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"};
static char PsyDaysFull[][10] = {"None", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"};
static char PsyMonths[][5] = {"None", "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
static char PsyMonthsFull[][10] = {"None", "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"};

struct PsyDateAndTime {
	uint32 usec;      /* microseconds after the minute - [0,999999] */
	uint32 msec;      /* milliseconds after the minute - [0,999] */
	uint16 sec;       /* seconds after the minute - [0,59] */
	uint16 min;       /* minutes after the hour - [0,59] */
	uint16 hour;      /* hours since midnight - [0,23] */
	uint16 day;      /* day of the month - [1,31] */
	uint16 mon;       /* months since January - [1,12] */
	uint16 year;      /* years since 0000 */
	uint16 wday;      /* day of the week - [1,7] */
	uint16 yday;      /* day of the year - [1,366] */
	bool negative;    /* is the time value negative */
	bool dst;         /* daylight savings in effect */
	int32 dstsec;     /* daylight savings in minutes when in effect */
	int32 tzsec;	  /* timezone in sec */
	char zonename[64];  /* the name of the current time zone */
};

// Return current time according to the TMC
uint64 GetTimeNow();

// Calculate the current Time Mapping Constant
uint64 SyncToHardwareClock();
bool SetCurrentNetSyncDif(int64 netTimeDif);
bool SetCurrentTimeSyncData(uint64 tmc, int64 netTimeAdjust);
bool GetCurrentTimeSyncData(uint64& tmc, int64& netTimeAdjust);
//bool SetLocalSyncAdjustment(int64 adjust);
//bool ChangeLocalSyncAdjustment(int64 adjust);

#define TMC_MASTER 0
#define TMC_SLAVE 1
#define TMC_SYNC_INTERVAL 60000000	// 1 minute

static uint64 CurrentTMC = 0;
static uint8 CurrentTMCMode = TMC_MASTER;
static uint64 LastTMCSync = 0;
static int64 NetTimeAdjust = 0;

// Estimate the next TMC wrap-around
uint64 EstNextTMCWrap();

// Return age of a timestamp compared to NOW
int64 GetTimeAge(uint64 t);
int32 GetTimeAgeMS(uint64 t);
uint64 GetTimeFromString(const char* str);
uint32 GetHTTPTime(uint64 time, char* buffer, uint32 size);
uint64 GetTimeFromPsyDateAndTime(struct PsyDateAndTime &tad);

uint32 GetTimeOffsetGMT();

struct PsyDateAndTime GetDateAndTime(uint64 t, bool local = true);
struct PsyDateAndTime GetDateAndTimeUTC(uint64 t);

struct PsyDateAndTime GetTimeDifference(uint64 t1, uint64 t2);
struct PsyDateAndTime GetTimeDifference(int64 dif);

char* PrintTime(uint64 t, bool local = true, bool us = true, bool ms = true);
char* PrintTimeOnly(uint64 t, bool local = true, bool us = true, bool ms = true);
char* PrintTimeDif(uint64 t, bool us = true, bool ms = true);
char* PrintDate(uint64 t, bool local = true);
char* PrintDateSortable(uint64 t, bool local = true);
char* PrintDateSortableDelimiter(uint64 t, const char* del, bool local = true);

char* PrintTimeSortable(uint64 t, bool local);
char* PrintTimeSortableMillisec(uint64 t, bool local);
char* PrintTimeSortableMicrosec(uint64 t, bool local);

std::string PrintTimeNowString(bool local = true, bool us = true, bool ms = true);
std::string PrintTimeString(uint64 t, bool local = true, bool us = true, bool ms = true);
std::string PrintTimeOnlyString(uint64 t, bool local = true, bool us = true, bool ms = true);
std::string PrintTimeDifString(uint64 t, bool us = true, bool ms = true);
std::string PrintDateString(uint64 t, bool local = true);
std::string PrintDateStringSortable(uint64 t, bool local = true);
std::string PrintDateStringSortableDelimiter(uint64 t, const char* del, bool local = true);

std::string PrintTimeSortableString(uint64 t, bool local = true);
std::string PrintTimeSortableMillisecString(uint64 t, bool local = true);
std::string PrintTimeSortableMicrosecString(uint64 t, bool local = true);

uint64 FTime2PsyTime(uint64 t);

bool PsyTime_UnitTest();

} // namespace cmlabs

#endif //_PSYTIME_H_

