/***************************************************************************
 *   Copyright (C) 2005-2008 by Eugene V. Lyubimkin aka jackyf             *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License                  *
 *   (version 3 or above) as published by the Free Software Foundation.    *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU GPL                        *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA               *
 ***************************************************************************/
#include <cstdio>
#include <cmath>

#include <yf/defs.hpp>

#include <yf/time/time.hpp>

namespace yf
{
	//--------------------------------------------------------------
	precise_time_t precise_time()
	{
		#ifdef OS_WINDOWS
			precise_time_t mt;
			static_assert(sizeof(precise_time_t) == sizeof (LARGE_INTEGER));
			QueryPerformanceCounter((LARGE_INTEGER*)&mt);
			return mt;
		#elif defined(OS_LINUX)
			struct timeval tv;
			struct timezone tz;
			gettimeofday(&tv, &tz);
			return tv;
		#else
			#error yf::micro_time() - Unsupported OS
		#endif
	}
	//--------------------------------------------------------------
	double get_micro_time( precise_time_t mt_beg, precise_time_t mt_end )
	{
		#ifdef OS_WINDOWS
			double time = (double)( mt_end - mt_beg );
			precise_time_t mt_freq;
			QueryPerformanceFrequency((LARGE_INTEGER*)&mt_freq);
			return time / (precise_time_t)mt_freq;
		#elif defined(OS_LINUX)
			ulong time;
			time = mt_end.tv_sec - mt_beg.tv_sec;
			time *= microsec_in_second;
			time += mt_end.tv_usec;
			time -= mt_beg.tv_usec;
			return (double)time / microsec_in_second;
		#else
			#error yf::get_micro_time() - Unsupported OS
		#endif
	}
	//------------------------------------------------------------------------------
	void write_milli_time( precise_time_t mt_beg, precise_time_t mt_end, std::ostream& os )
	{
		float time = get_milli_time( mt_beg, mt_end );
		char buf[80];
		sprintf( buf, "%2d min %.3f sec\n",
			(int)(time / sec_in_minute),
			std::fmod(time, sec_in_minute)
			);
		os << buf;
	}
	//--------------------------------------------------------------
	void write_micro_time( precise_time_t mt_beg, precise_time_t mt_end, std::ostream& os )
	{
		char buf[80];
		sprintf( buf, "%.6f sec\n", get_micro_time( mt_beg, mt_end ) );
		os << buf;
	}
}


