#include "Util.h"

#include <sys/time.h>

#define SEC_TO_MICROSEC    (1000000LL)


/// @brief  현재 시간 정보를 micro-second 단위로 계산하여 반환
/// @return 1970년 1월 1일 이후부터의 현재시간을 micro-second(1/1,000,000) 단위로 반환처리, 오류발생시에는 -1 값을 반환.
long long longtime_now()
{
	struct timeval tv;
	
	if( gettimeofday(&tv, NULL) == 0 )
	{
		// 성공시 micro-second 단위의 값을 반환
		return tv.tv_sec * SEC_TO_MICROSEC + tv.tv_usec;
	}
	else
	{
		// 실패시 -1 값을 반환.
		return -1;
	}
}

/// @brief  source string에 주어진 search string을 replacement로 변환 화여 반환
std::string stringreplace(const std::string& source, const std::string search, const std::string replacement) 
{
	std::string r = source;

	std::string::size_type pos = 0;

	while ( (pos = r.find(search, pos)) != std::string::npos ) 
	{
		r.replace( pos, search.size(), replacement );
		pos = pos + replacement.size();		
	}

	return r;
}

std::string strtime_now()
{
	time_t rawtime;
	struct tm * timeinfo;
	char buffer[16] = { 0 };

	time(&rawtime);
	timeinfo = localtime(&rawtime);

	if (strftime(buffer, sizeof buffer, "%Y%m%d%H%M%S", timeinfo) <= 0)
		return "";

	return std::string(buffer);
}

time_t str2time_t(std::string strtime)
{
	struct tm tm = { 0 };

	if (strtime == "0")
		return 0;

	if (strptime(strtime.c_str(), "%Y%m%d%H%M%S", &tm) == NULL)
		return -1;

	return mktime(&tm);
}

std::string time_t2string(time_t rawtime)
{
	struct tm * timeinfo;
	char buffer[16] = { 0 };

	timeinfo = localtime(&rawtime);

	if (strftime(buffer, sizeof buffer, "%Y%m%d%H%M%S", timeinfo) <= 0)
		return "";

	return std::string(buffer);
}

long long str2longtime(std::string strtime)
{
	return str2time_t(strtime) * SEC_TO_MICROSEC;
}

void StringSplit(std::string str, std::string delim, std::vector<std::string> &results, bool bUseEmpty /*= false*/)
{
	const std::string strEmpty("");
	std::string::size_type cutAt;

	while ((cutAt = str.find_first_of(delim)) != str.npos)
	{
		if (cutAt > 0)
		{
			results.push_back(str.substr(0, cutAt));
		}
		else
		{
			if (bUseEmpty && cutAt == 0)
				results.push_back(strEmpty);
		}
		str = str.substr(cutAt + 1);
	}
	if (str.length() > 0)
	{
		results.push_back(str);
	}
}

void solusleep(unsigned long usec)
{
	// usleep 사용시 multi thread 환경에서 block 발생 가능성이 존재
	// 이에 nanosleep 함수를 사용토록 수정 처리함.
	struct timespec sleep;

	if (usec >= 1000000)
	{
		sleep.tv_sec = (int)(usec / 1000000);
		sleep.tv_nsec = (usec - ((long)sleep.tv_sec * 1000000)) * 1000;
	}
	else
	{
		sleep.tv_sec = 0;
		sleep.tv_nsec = usec * 1000;
	}

	nanosleep(&sleep, NULL);
}