#include "Utils.h"
#include <thread>
#include <chrono>
#include <iostream>
#include <filesystem>
#include <fstream>
using namespace std;

std::string Utils::toHex(std::vector<unsigned char>& s, int len/*=0*/)
{
	if (len == 0) len = s.size();
	std::stringstream ss;
	for (int i = 0; i < len; ++i)
	{
		ss << std::hex << std::setw(2) << std::setfill('0') << (int)s[i];
	}
	return ss.str();
}
std::string Utils::toHex(const std::string& s)
{
	std::stringstream ss;
	for (int i = 0; i < s.size(); ++i) 
	{
		ss << std::hex << std::setw(2) << std::setfill('0') << (int)static_cast<unsigned char>(s[i]);
	}
	return ss.str();
}
std::string Utils::fromHex(const std::string& hexstr)
{
	std::vector<uint8_t> result;
	result.reserve(hexstr.size() / 2);
	for (std::string::const_iterator it = hexstr.begin(); it != hexstr.end(); it += 2)
	{
		result.push_back(static_cast<char>(strtol(std::string(it, it + 2).c_str(), nullptr, 16)));
	}
	return std::string(result.begin(), result.end());
}

#include <iostream>
string Utils::fromHexText(string s)
{
	vector<unsigned char> result;
	string tmp;
	stringstream ss;
	int v;
	for (auto ch : s)
	{
		if ((ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F'))
		{
			tmp += ch;
			if (tmp.size() == 2)
			{
				ss.clear();
				ss.str("");
				ss << hex << tmp;
				ss >> v;
				result.emplace_back((unsigned char)v);
				tmp.clear();
			}
		}
	}
	return string(result.begin(), result.end());
}
string Utils::toHexText(string s, string d/* = " "*/)
{
	stringstream ss;
	for (unsigned int i = 0; i < s.size(); ++i)
	{
		ss << std::setw(2) << std::setfill('0') << std::hex << std::uppercase << (int)static_cast<unsigned char>(s[i]) << ((i < s.size() - 1) ? d : "");
	}
	return ss.str();
}

int64_t Utils::hexBinToInt(const string& str, bool swap/*=false*/)
{
	int64_t v = 0;
	for (size_t i = 0; i < str.size(); i++)
	{
		if (swap)
		{
			v = v + (str[str.size() - 1 - i] << (str.size() - 1 - i) * 8);
		}
		else
		{
			v = v + (str[i] << (str.size() - 1 - i) * 8);
		}
	}
	return v;
}

int Utils::hexStrToInt(const std::string& str)
{
	stringstream ss;
	int ret;
	ss << hex << str.c_str();
	ss >> ret;
	return ret;
}

string Utils::toStr(int v)
{
	return std::to_string(v);
}

string Utils::toStr(float v, int precision)
{
	stringstream ss;
	ss.precision(precision);
	ss.setf(std::ios::fixed);
	ss << v;
	return ss.str();
}

string Utils::toStr(double v, int precision)
{
	stringstream ss;
	ss.precision(precision);
	ss.setf(std::ios::fixed);
	ss << v;
	return ss.str();
}

int Utils::toInt(const std::string& str)
{
	stringstream ss(str);
	int ret = 0;
	ss >> ret;
	return ret;
}
float Utils::toFloat(const string& str)
{
	stringstream ss(str);
	float ret = 0.0f;
	ss >> ret;
	return ret;
}
double Utils::toDouble(const std::string& str)
{
	stringstream ss(str);
	double ret = 0.0;
	ss >> ret;
	return ret;
}




//string Utils::fromHexText1(string s)
//{
//    vector<unsigned char> result;
//    string tmp = s;
//    stringstream ss;
//    int v;
//    size_t pos = 0;
//    while (!tmp.empty())
//    {
//        if (pos >= tmp.size()) {
//            ss.clear();
//            ss.str("");
//            ss << hex << tmp;
//            ss >> v;
//            result.emplace_back((unsigned char)v);
//            tmp = "";
//            break;
//        }
//        auto& ch = tmp[pos];
//        bool flag = (ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F');
//        if (!flag) {
//            ss.clear();
//            ss.str("");
//            ss << hex << tmp.substr(0, pos);
//            ss >> v;
//            tmp = tmp.substr(pos + 1);
//            result.emplace_back((unsigned char)v);
//            pos = 0;
//        }
//        ++pos;
//    }
//    return string(result.begin(), result.end());
//}



void time_point_to_duration()
{
	auto tp = chrono::system_clock::now();

	auto seconds = chrono::duration_cast<chrono::seconds>(tp.time_since_epoch());
	cout << seconds.count() << " s" << endl;//seconds from 1970

	auto ms = chrono::duration_cast<chrono::milliseconds>(tp.time_since_epoch());
	cout << ms.count() << " ms" << endl;

	auto us = chrono::duration_cast<chrono::microseconds>(tp.time_since_epoch());
	cout << us.count() << " us" << endl;

	auto ns = chrono::duration_cast<chrono::nanoseconds>(tp.time_since_epoch());
	cout << ns.count() << " ns" << endl;

	cout << tp.time_since_epoch().count() << " default is ns" << endl;
}

void duration_to_time_point()
{
	std::uint64_t ticker = 1609756793160376465;
	auto ns = chrono::nanoseconds(ticker);

	auto tp1 = chrono::time_point<chrono::system_clock, chrono::nanoseconds>(ns);
	auto tp2 = tp1 - chrono::hours(1);//time point before one hour
	cout << "tp1=" << tp1.time_since_epoch().count() << endl << "tp2=" << tp2.time_since_epoch().count() << endl;
}

void format_time_point()
{
	auto tp = chrono::system_clock::now();
	auto time = chrono::system_clock::to_time_t(tp);
	std::stringstream ss;
	ss << std::put_time(std::localtime(&time), "%Y-%m-%d %H:%M:%S");

	cout << ss.str() << endl;
}

void parse_from_string()
{
	std::stringstream ss;
	ss << "2021-01-06 18:47:35";

	std::tm tm{};
	ss >> std::get_time(&tm, "%Y-%m-%d %H:%M:%S");
	auto tp = chrono::system_clock::from_time_t(std::mktime(&tm));
	cout << tp.time_since_epoch().count() << endl;
}

int64_t Utils::time(std::string s/* = ""*/)
{
	if (s.empty())
	{
		//return chrono::time_point_cast<chrono::microseconds>(chrono::system_clock::now()).time_since_epoch().count();
		return chrono::duration_cast<chrono::seconds>(chrono::system_clock::now().time_since_epoch()).count();
	}

	static const std::string T = "1987/01/01 00/00/00";
	// YYYY/mm/dd HH/MM/SS
	int len = T.size();
	int size = s.size();
	if (size < len) { s += T.substr(size, len-size); }
	s[4] = s[7] = s[13] = s[16] = '/';
	s[10] = ' ';
	std::tm t;
	std::stringstream ss(s);
	ss >> std::get_time(&t, "%Y/%m/%d %H/%M/%S");
	auto tp = chrono::system_clock::from_time_t(std::mktime(&t));
	return chrono::duration_cast<chrono::seconds>(tp.time_since_epoch()).count();
}

string Utils::timeStr(int64_t ts, std::string fmt /*= "%Y-%m-%dT%H:%M:%S"*/)
{
	time_t t;
	if (ts == 0)
	{
		t = chrono::system_clock::to_time_t(chrono::system_clock::now());
	}
	else
	{
		auto tp = chrono::time_point<chrono::system_clock>(chrono::seconds(ts));
		t = chrono::system_clock::to_time_t(tp);
	}
	std::stringstream ss;
	ss << std::put_time(std::localtime(&t), fmt.c_str());
	return ss.str();
}

int64_t Utils::date()
{
	// 获取当前时间戳
	std::time_t t = chrono::system_clock::to_time_t(chrono::system_clock::now());
	
	// 转换为本地时间结构体，设置时分秒为0
	std::tm* tmlocal = localtime(&t);
	tmlocal->tm_hour = 0;
	tmlocal->tm_min = 0;
	tmlocal->tm_sec = 0;

	auto tp = chrono::time_point_cast<chrono::seconds>(chrono::system_clock::from_time_t(mktime(tmlocal)));
	return tp.time_since_epoch().count();
}

string Utils::dateStr(int64_t ts, std::string fmt /*= "%Y-%m-%d %H:%M:%S"*/)
{
	return Utils::timeStr(ts, fmt).substr(0, 10);
}


string Utils::timeStrMS(std::string fmt /*= "%Y-%m-%dT%H:%M:%S"*/)
{
	auto tpNow = chrono::system_clock::now();
	auto time = chrono::system_clock::to_time_t(tpNow);

	std::stringstream ss;
	ss << std::put_time(std::localtime(&time), fmt.c_str());

	auto epoch = tpNow.time_since_epoch();
	auto tms = chrono::duration_cast<chrono::milliseconds>(epoch);
	auto tseconds = chrono::duration_cast<chrono::seconds>(epoch);
	ss << "." << std::setfill('0') << std::setw(3) << (tms - tseconds).count();
	return ss.str();
}
//
//string Utils::timeStr(int64_t ts, std::string fmt /*= "%Y-%m-%d %H:%M:%S"*/)
//{
//	// std::localtime : 本地时区的时间
//	// std::gmtime : 格林威治时间
//	time_t t(ts);
//	std::stringstream ss;
//	ss << std::put_time(std::localtime(&t), fmt.c_str());
//	return ss.str();
//}
//
//string Utils::time_to_string(int64_t dt, std::string fmt /*= "%Y-%m-%d %H:%M:%S"*/)
//{
//	auto ms = chrono::milliseconds(dt);
//	auto tp = chrono::time_point<chrono::system_clock>(ms);
//	time_t t = chrono::system_clock::to_time_t(tp);
//	std::stringstream ss;
//	ss << std::put_time(std::localtime(&t), fmt.c_str());
//	return ss.str();
//}
//
//// 2023-12-12 12:12:12
//int64_t Utils::time(string dt, int zone)
//{
//	if (dt.empty())
//	{
//		return chrono::time_point_cast<chrono::seconds>(chrono::system_clock::now()).time_since_epoch().count();
//	}
//	else
//	{
//		static string FMT_D = "yyyy-MM-dd";
//		static string FMT_DT = "yyyy-MM-dd HH:mm:ss";
//		static string FMT_DS = "yyyy-MM-dd HH:mm:ss.SSS";
//		string fmt;
//		if (dt.size() == FMT_D.size())
//		{
//			fmt = "%Y-%m-%d";
//			dt[4] = dt[7] = '-';
//		}
//		else if (dt.size() == FMT_DT.size())
//		{
//			fmt = "%Y-%m-%d %H:%M:%S";
//			dt[4] = dt[7] = '-';
//			dt[10] = ' ';
//			dt[13] = dt[16] = ':';
//		}
//		else if (dt.size() == FMT_DT.size())
//		{
//		}
//		else
//		{
//			return -1;
//		}
//
//		stringstream ss(dt);
//
//		std::tm t {};
//		ss >> std::get_time(&t, fmt.c_str());
//		t.tm_hour += zone;
//		auto tp = chrono::system_clock::from_time_t(std::mktime(&t));
//		return chrono::duration_cast<chrono::seconds>(tp.time_since_epoch()).count();
//		//return chrono::duration_cast<chrono::milliseconds>(tp.time_since_epoch()).count();
//	}
//}
//
//
//
//bool Utils::time_string_to_tm(string dt, std::tm& t)
//{
//	t.tm_year = 1900;
//	t.tm_mon = 1;
//	t.tm_mday = 1;
//	static string FORMAT_D = "yyyy-mm-dd";
//	static string FORMAT_DT = "yyyy-mm-dd HH:MM:SS";
//	string fmt;
//	if (dt.size() == FORMAT_D.size())
//	{
//		fmt = "%Y-%m-%d";
//		dt[4] = dt[7] = '-';
//	}
//	else if (dt.size() >= FORMAT_DT.size())
//	{
//		fmt = "%Y-%m-%d %H:%M:%S";
//		dt[4] = dt[7] = '-';
//		dt[10] = ' ';
//		dt[13] = dt[16] = ':';
//	}
//	else
//	{
//		return false;
//	}
//	stringstream ss;
//	ss << dt;
//	ss >> std::get_time(&t, fmt.c_str());
//	t.tm_year += 1900;
//	t.tm_mon += 1;
//	return true;
//}

int64_t Utils::timeDaySeconds()
{
	// 获取当前时间
	auto tpNow = chrono::system_clock::now();
	// 转换为time_t以便使用C库函数
	std::time_t tsNow = std::chrono::system_clock::to_time_t(tpNow);
	std::tm* tmLocal = std::localtime(&tsNow);

	// 设置为今日0点
	tmLocal->tm_hour = 0;
	tmLocal->tm_min = 0;
	tmLocal->tm_sec = 0;

	// 转换回时间戳
	std::time_t tsDay = std::mktime(tmLocal);
	return tsNow - tsDay;
}

void Utils::sleepMS(int ms)
{
	std::this_thread::sleep_for(chrono::milliseconds(ms));
}


#include <Windows.h>

unsigned short Utils::crc16(unsigned char* data, unsigned int len)
{
	if (data == NULL || len == 0)
	{
		return 0;
	}
	unsigned short crc = 0xffff;
	unsigned short FACTOR = 0xa001;

	for (int i = 0; i < len; i++)
	{
		crc ^= data[i];
		for (int j = 0; j < 8; j++)
		{
			if ((crc & 0x0001) != 0)
			{
				crc >>= 1;
				crc ^= FACTOR;
			}
			else
			{
				crc >>= 1;
			}
		}
	}
	//(unsigned char)(CRC & 0x00ff);
	//(unsigned char)(CRC >> 8);
	return crc;
}

string Utils::gbkToUtf8(string s)
{
	int n = MultiByteToWideChar(CP_ACP, 0, s.c_str(), -1, NULL, 0);
	WCHAR* str1 = new WCHAR[n];
	MultiByteToWideChar(CP_ACP, 0, s.c_str(), -1, str1, n);
	n = WideCharToMultiByte(CP_UTF8, 0, str1, -1, NULL, 0, NULL, NULL);
	vector<char> s_utf8(n, 0);
	WideCharToMultiByte(CP_UTF8, 0, str1, -1, &s_utf8[0], n, NULL, NULL);
	delete[]str1;
	str1 = NULL;
	return string(s_utf8.begin(), s_utf8.end());
}

string Utils::utf8ToGbk(string s)
{
	string s_gbk = "";
	int n = MultiByteToWideChar(CP_UTF8, 0, s.c_str(), -1, NULL, 0);
	WCHAR* str1 = new WCHAR[n];
	MultiByteToWideChar(CP_UTF8, 0, s.c_str(), -1, str1, n);
	n = WideCharToMultiByte(CP_ACP, 0, str1, -1, NULL, 0, NULL, NULL);
	char* str2 = new char[n];
	WideCharToMultiByte(CP_ACP, 0, str1, -1, str2, n, NULL, NULL);
	s_gbk = str2;
	delete[] str1;
	str1 = NULL;
	delete[] str2;
	str2 = NULL;
	return s_gbk;
}

#include <random>
int Utils::random(int min, int max)
{
	//生成 a 到 b 之间（包含）均匀分布的随机数
	uniform_int_distribution<unsigned> rand_u(min, max);
	static default_random_engine rand_e;    // 生成无符号随机整数
	return rand_u(rand_e);
}

void Utils::split(string buf, string c, vector<string>& res)
{
	if (buf.size() == 0 || c.size() == 0)
	{
		return;
	}

	string tmp = buf;
	while (true)
	{
		auto pos = tmp.find_first_of(c);
		if (pos == string::npos)
		{
			res.push_back(tmp);
			break;
		}
		res.push_back((pos == 0) ? "" : tmp.substr(0, pos));
		tmp = tmp.substr(pos + c.size());
	}
}

std::string Utils::readFile(std::string filename)
{
	std::filesystem::path filePath = std::filesystem::u8path(filename);
	//std::locale::global(locale(""));//将全局区域设为操作系统默认区域
	std::ifstream ifs(filePath, std::ios::binary);
	//std::locale::global(locale("C"));//还原全局区域设定

	if (ifs.is_open())
	{
		// 将文件指针移动到末尾获取文件大小
		ifs.seekg(0, std::ios::end);
		std::streamsize size = ifs.tellg();
		ifs.seekg(0, std::ios::beg);

		std::string buf(size, '\0');
		ifs.read(&buf[0], size);
		return buf;
	}
	else
	{
		std::cout << "error" << std::endl;
		return "";
	}
}


