#include "pch.h"

#include "StringUtil.h"
#include <algorithm> // std::equal
#include <locale>   // std::tolower

// для работы с std::wstring нет многих стандартных нужных функций.

std::string strUtil::trim(const std::string &str, const char trim_char /*= L' '*/)
{
	auto res = trimLeft(str, trim_char);
	return trimRight(res, trim_char);
}

std::wstring strUtil::trim(const std::wstring &str, const wchar_t trim_char)
{
	auto res = trimLeft(str, trim_char);
	return trimRight(res, trim_char);
}


std::string strUtil::trimLeft(const std::string &str, const char trim_char /*= L' '*/)
{
	auto res = str;

	while (!res.empty() && (res.front() == trim_char))
	{
		res.erase(res.begin());
	}

	return res;
}

std::wstring strUtil::trimLeft(const std::wstring &str, const wchar_t trim_char)
{
	auto res = str;

	while (!res.empty() && (res.front() == trim_char))
	{
		res.erase(res.begin());
	}

	return res;
}

std::string strUtil::trimRight(const std::string &str, const char trim_char /*= L' '*/)
{
	auto res = str;

	while (!res.empty() && (res.back() == trim_char))
	{
		res.pop_back();
	}

	return res;
}

std::wstring strUtil::trimRight(const std::wstring &str, const wchar_t trim_char)
{
	auto res = str;

	while (!res.empty() && (res.back() == trim_char))
	{
		res.pop_back();
	}

	return res;
}

std::string strUtil::replaceChar(const std::string &str, const char src, const char dst)
{
	if (!str.empty())
	{
		std::string res;

		for (auto wch : str)
		{
			if (wch == src)
			{
				wch = dst;
			}

			res.push_back(wch);
		}

		return res;
	}

	return str;
}

std::wstring strUtil::replaceChar(const std::wstring &str, const wchar_t src, const wchar_t dst)
{
	if (!str.empty())
	{
		std::wstring res;

		for (auto wch : str)
		{
			if (wch == src)
			{
				wch = dst;
			}

			res.push_back(wch);
		}

		return res;
	}

	return str;
}

std::string strUtil::replaceChars(const std::string &str, const std::string &src, const char dst)
{
	if (!str.empty() && !src.empty())
	{
		std::string res;

		for (auto wch : str)
		{
			for (auto s : src)
			{
				if (wch == s)
				{
					wch = dst;
					break;
				}
			}

			res.push_back(wch);
		}

		return res;
	}

	return str;
}

std::wstring strUtil::replaceChars(const std::wstring &str, const std::wstring &src, const wchar_t dst)
{
	if (!str.empty() && !src.empty())
	{
		std::wstring res;

		for (auto wch : str)
		{
			for (auto s : src)
			{
				if (wch == s)
				{
					wch = dst;
					break;
				}
			}

			res.push_back(wch);
		}

		return res;
	}

	return str;
}

std::string strUtil::strToUpper(const std::string &str)
{
	std::string res;

	if (!str.empty())
	{
		std::locale loc("ru_RU");

		for (auto n : str)
		{
			res.push_back(std::toupper(n, loc));
		}
	}

	return res;
}

std::wstring strUtil::strToUpper(const std::wstring &str)
{
	std::wstring res;

	if (!str.empty())
	{
		std::locale loc("ru_RU");

		for (auto n : str)
		{
			res.push_back(std::toupper(n, loc));
		}
	}

	return res;
}

std::string strUtil::strToLower(const std::string &str)
{
	std::string res;

	if (!str.empty())
	{
		std::locale loc("ru_RU");

		for (auto n : str)
		{
			res.push_back(std::tolower(n, loc));
		}
	}

	return res;
}

std::wstring strUtil::strToLower(const std::wstring &str)
{
	std::wstring res;

	if (!str.empty())
	{
		std::locale loc("ru_RU");

		for (auto n : str)
		{
			res.push_back(std::tolower(n, loc));
		}
	}

	return res;
}


// сокращение строки до заданной длины.
// Вход: str - строка
// len - желаемая длина
// Выход: сформированная строка
std::string strUtil::CropStr(const std::string &str, const size_t len)
{
	auto res = trim(str);

	if (res.length() >= len)
	{
		auto crop = res.substr(0, len - 1); // берём первые len-1 символов
		crop += res.back(); // и берём самый последний символ
		return crop;
	}

	return res;
}

std::wstring strUtil::CropStr(const std::wstring &str, const size_t len)
{
	auto res = trim(str);

	if (res.length() >= len)
	{
		auto crop = res.substr(0, len - 1); // берём первые len-1 символов
		crop += res.back(); // и берём самый последний символ
		return crop;
	}

	return res;
}


bool strUtil::equalNoCase(const std::string &a, const std::string &b)
{
	return std::equal(a.begin(), a.end(), b.begin(), b.end(), [ ](char a, char b)
	{
		auto loc = std::locale("ru_RU");
		return std::tolower(a, loc) == std::tolower(b, loc);
	});
}

bool strUtil::equalNoCase(const std::wstring &a, const std::wstring &b)
{
	return std::equal(a.begin(), a.end(), b.begin(), b.end(), [](wchar_t a, wchar_t b)
	{
		auto loc = std::locale("ru_RU");
		return std::tolower(a, loc) == std::tolower(b, loc);
	});
}



#if !defined(_WIN32)
#include <codecvt>

std::wstring strUtil::s2ws(const std::string &str)
{
	using convert_typeX = std::codecvt_utf8<wchar_t>;
	std::wstring_convert<convert_typeX, wchar_t> converterX;
	return converterX.from_bytes(str);
}

std::string strUtil::ws2s(const std::wstring &wstr)
{
	using convert_typeX = std::codecvt_utf8<wchar_t>;
	std::wstring_convert<convert_typeX, wchar_t> converterX;
	return converterX.to_bytes(wstr);
}
#endif
