// Common
// Copyright 2001 lexander Liss

//     	AUniTime class implementation

#include <pthread.h>
#include "AUniTime.h"
#include <string.h>
//#include <time.h> // clock_gettime()

int AUniTime::set_current()
{
/*  alternative implementation:
	
	timeval t;
	
	gettimeofday(&t,0);
	
	put_timeval(t);
*/
	timespec t;
	
 	int g=clock_gettime(CLOCK_REALTIME,&t);
 	
 	if(g < 0) return -1;
 	
 	put_timespec(t);
 	
 	return 0;

}

int AUniTime::set_current_plus(unsigned milliseconds)
{
	AUniTime current_time;
	current_time.set_current();
	
	put_milliseconds(milliseconds);
	operator+=(current_time);

	return 0;
}
	
AUniTime& AUniTime::operator += (const AUniTime& z)
{
	seconds+=z.seconds;
	nanoseconds+=z.nanoseconds;
	if(nanoseconds >= 1000000000)
	{
		++seconds;
		nanoseconds -= 1000000000;
	}
	return *this;
}

// to do - make thread safe (localtime_r ?) - returns static structure,
// is it thread specific?
int AUniTime::get_local_tm(tm& time)const
{
	int g=0;
	time_t t;
	g=get_time_t(t);
	if(!g) memcpy(&time,localtime(&t),sizeof(tm));
	return g;
}

bool AUniTime::in_past()const
{
	AUniTime current;
	current.set_current();
	
	if(compare(current,*this)>=0) return true;

	return false;
}

int AUniTime::left(unsigned& z)const
{ int g=0;

	AUniTime current;
	current.set_current();
	
	g=compare(current,*this);
	
	if(g < 0) return 1;
	
	if(g == 0)
	{
		z=0;
		return 0;
	}
	
	AUniTime r;
	g=sub(r,current,*this);
	if(g) return 2;
	
	g=r.get_milliseconds(z);
	if(g) return 3;

	return 0;
}

int compare(const AUniTime& z1,const AUniTime& z2)
{
	if(z1.seconds > z2.seconds) return 1;
	if(z1.seconds < z2.seconds) return -1;
	if(z1.nanoseconds > z2.nanoseconds) return 1;
	if(z1.nanoseconds < z2.nanoseconds) return -1;
	
	return 0;
}

// r = a - b, if a >= b
int sub(AUniTime& r,const AUniTime& a,const AUniTime& b)
{
	if(a.seconds<b.seconds) return 1;
	if(a.seconds==b.seconds && a.nanoseconds<b.nanoseconds) return 1;
	
	r.seconds=a.seconds-b.seconds;
	r.nanoseconds=a.nanoseconds;
	if(b.nanoseconds>r.nanoseconds)
	{
		r.nanoseconds+=1000000000;
		--r.seconds;
	}
	r.nanoseconds-=b.nanoseconds;
	
	return 0;
}