#include "pch.h"
#include <WinNls.h>
#include "StringHelper.h"
#include <string>

using namespace std;

bool cmpIngoreCase(const string& s1, const string& s2)
{
	if (s1.length() != s2.length()) return false;

	return std::equal(s1.begin(), s1.end(), s2.begin(),
		[](char a, char b)->bool
		{
			return tolower(a) == tolower(b);
		});
}

bool cmpIngoreCase(const std::string& s1, const char* s2)
{
	if (s1.length() != strlen(s2)) return false;

	return std::equal(s1.begin(), s1.end(), string_view(s2).begin(),
		[](char a, char b)->bool
		{
			return tolower(a) == tolower(b);
		});
}

bool cmpIngoreCase(const wstring& s1, const wstring& s2)
{
	if (s1.length() != s2.length()) return false;

	return std::equal(s1.begin(), s1.end(), s2.begin(),
		[](wchar_t a, wchar_t b)->bool
		{
			return tolower(a) == tolower(b);
		});
}

bool cmpIngoreCase(const std::wstring& s1, const wchar_t* s2)
{
	if (s1.length() != wcslen(s2)) return false;

	return std::equal(s1.begin(), s1.end(), wstring_view(s2).begin(),
		[](wchar_t a, wchar_t b)->bool
		{
			return tolower(a) == tolower(b);
		});
}

// Convert a wide Unicode string to an UTF8 string
std::string  utf16_8(const std::wstring& wstr)
{
	if (wstr.empty()) return std::string();
	int size_needed = WideCharToMultiByte(CP_UTF8, 0, &wstr[0], (int)wstr.size(), NULL, 0, NULL, NULL);
	std::string strTo(size_needed, 0);
	WideCharToMultiByte(CP_UTF8, 0, &wstr[0], (int)wstr.size(), &strTo[0], size_needed, NULL, NULL);
	return strTo;
}

std::string  utf16_8(const wchar_t* wstr)
{
	if (wstr == nullptr) return std::string();
	int srclen = int(wcslen(wstr));
	if (srclen == 0) return std::string();
	int size_needed = WideCharToMultiByte(CP_UTF8, 0, wstr, srclen, NULL, 0, NULL, NULL);
	std::string strTo(size_needed, 0);
	WideCharToMultiByte(CP_UTF8, 0, wstr, srclen, &strTo[0], size_needed, NULL, NULL);
	return strTo;
}

int  utf16_8(const wchar_t* wstr, char* dst, int dstsize)
{
	if (wstr == nullptr) return 0;
	int size_needed = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, NULL, 0, NULL, NULL);
	if (size_needed > dstsize) {
		return 0;
	}
	WideCharToMultiByte(CP_UTF8, 0, wstr, -1, dst, size_needed, NULL, NULL);
	return size_needed;
}

std::string  Utf16ToGBK(const wchar_t* wstr)
{
	if (wstr == nullptr) return std::string();
	int srclen = int(wcslen(wstr));
	if (srclen == 0) return std::string();
	int size_needed = WideCharToMultiByte(CP_ACP, 0, wstr, srclen, NULL, 0, NULL, NULL);
	std::string strTo(size_needed, 0);
	WideCharToMultiByte(CP_ACP, 0, wstr, srclen, &strTo[0], size_needed, NULL, NULL);
	return strTo;
}

int  Utf16ToGBK(const wchar_t* wstr, char* dst, int dstsize)
{
	if (wstr == nullptr) return 0;
	int size_needed = WideCharToMultiByte(CP_ACP, 0, wstr, -1, NULL, 0, NULL, NULL);
	if (size_needed > dstsize) {
		return 0;
	}
	WideCharToMultiByte(CP_ACP, 0, wstr, -1, dst, size_needed, NULL, NULL);
	return size_needed;
}

// Convert an UTF8 string to a wide Unicode String
std::wstring  utf8_16(const std::string& str)
{
	if (str.empty()) return std::wstring();
	int size_needed = MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), NULL, 0);
	std::wstring wstrTo(size_needed, 0);
	MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), &wstrTo[0], size_needed);
	return wstrTo;
}

std::wstring  utf8_16(const char* str)
{
	if (str == nullptr) return std::wstring();
	int srclen = int(strlen(str));
	if (srclen == 0) return std::wstring();
	int size_needed = MultiByteToWideChar(CP_UTF8, 0, str, srclen, NULL, 0);
	std::wstring strTo(size_needed, 0);
	MultiByteToWideChar(CP_UTF8, 0, str, srclen, &strTo[0], size_needed);
	return strTo;
}


#ifdef _WIN32
std::string  GbkToUtf8(const std::string& src_str)
{
	int srclen = int(src_str.size());
	if (srclen == 0) return std::string();

	const auto tmpsize = MultiByteToWideChar(CP_ACP, 0, &src_str[0], srclen, NULL, 0);
	wchar_t* wstr = new wchar_t[tmpsize + 1];
	MultiByteToWideChar(CP_ACP, 0, &src_str[0], srclen, wstr, tmpsize);
	wstr[tmpsize] = 0;

	auto dstlen = WideCharToMultiByte(CP_UTF8, 0, wstr, tmpsize, NULL, 0, NULL, NULL);
	std::string dst_str(dstlen, 0);
	WideCharToMultiByte(CP_UTF8, 0, wstr, tmpsize, &dst_str[0], dstlen, NULL, NULL);
	delete[] wstr;
	return dst_str;
}

std::string  GbkToUtf8(const char* src_str)
{
	int srclen = int(strlen(src_str));
	if (srclen == 0) return std::string();

	const auto tmpsize = MultiByteToWideChar(CP_ACP, 0, src_str, srclen, NULL, 0);
	wchar_t* wstr = new wchar_t[tmpsize + 1];
	MultiByteToWideChar(CP_ACP, 0, src_str, srclen, wstr, tmpsize);
	wstr[tmpsize] = 0;

	auto dstlen = WideCharToMultiByte(CP_UTF8, 0, wstr, tmpsize, NULL, 0, NULL, NULL);
	std::string dst_str(dstlen, 0);
	WideCharToMultiByte(CP_UTF8, 0, wstr, tmpsize, &dst_str[0], dstlen, NULL, NULL);
	delete[] wstr;
	return dst_str;
}


std::string  Utf8ToGbk(const std::string& src_str)
{
	int srclen = int(src_str.size());
	if (srclen == 0) return std::string();

	const auto tmpsize = MultiByteToWideChar(CP_UTF8, 0, &src_str[0], srclen, NULL, 0);
	wchar_t* wstr = new wchar_t[tmpsize + 1];
	MultiByteToWideChar(CP_UTF8, 0, &src_str[0], srclen, wstr, tmpsize);
	wstr[tmpsize] = 0;

	auto dstlen = WideCharToMultiByte(CP_ACP, 0, wstr, tmpsize, NULL, 0, NULL, NULL);
	std::string dst_str(dstlen, 0);
	WideCharToMultiByte(CP_ACP, 0, wstr, tmpsize, &dst_str[0], dstlen, NULL, NULL);
	delete[] wstr;
	return dst_str;
}
std::string  Utf8ToGbk(const char* src_str)
{
	int srclen = int(strlen(src_str));
	if (srclen == 0) return std::string();

	const auto tmpsize = MultiByteToWideChar(CP_UTF8, 0, src_str, srclen, NULL, 0);
	wchar_t* wstr = new wchar_t[tmpsize + 1];
	MultiByteToWideChar(CP_UTF8, 0, src_str, srclen, wstr, tmpsize);
	wstr[tmpsize] = 0;

	auto dstlen = WideCharToMultiByte(CP_ACP, 0, wstr, tmpsize, NULL, 0, NULL, NULL);
	std::string dst_str(dstlen, 0);
	WideCharToMultiByte(CP_ACP, 0, wstr, tmpsize, &dst_str[0], dstlen, NULL, NULL);
	delete[] wstr;
	return dst_str;
}
#else
#include <iconv.h>

int GbkToUtf8(char* str_str, size_t src_len, char* dst_str, size_t dst_len)
{
	iconv_t cd;
	char** pin = &str_str;
	char** pout = &dst_str;

	cd = iconv_open("utf8", "gbk");
	if (cd == 0)
		return -1;
	memset(dst_str, 0, dst_len);
	if (iconv(cd, pin, &src_len, pout, &dst_len) == -1)
		return -1;
	iconv_close(cd);
	*pout = '\0';

	return 0;
}

int Utf8ToGbk(char* src_str, size_t src_len, char* dst_str, size_t dst_len)
{
	iconv_t cd;
	char** pin = &src_str;
	char** pout = &dst_str;

	cd = iconv_open("gbk", "utf8");
	if (cd == 0)
		return -1;
	memset(dst_str, 0, dst_len);
	if (iconv(cd, pin, &src_len, pout, &dst_len) == -1)
		return -1;
	iconv_close(cd);
	*pout = '\0';

	return 0;
}


#endif

