
#include "ml_string.h"


// Replace a substring with a replacement string in a source string
void replace_substring(std::string &src, const std::string &substr, const std::string &replacement) {
	size_t i = 0;
	for (i = src.find(substr, i); i != std::string::npos; i = src.find(substr, i)) {
		src.replace(i, substr.size(), replacement);
		i += replacement.size();
	}
}


// Returns true if where contains regex
bool regexp_search(const std::string &where, const std::string &regex_str) {
	// online tester https://www.regextester.com/97722
	std::regex regex(regex_str);
	std::smatch match;

	if (std::regex_search(where, match, regex)) {
		// std::cout << "matches for '" << where << "'\n";
		// std::cout << "Prefix: '" << match.prefix() << "'\n";
		// for (size_t i = 0; i < match.size(); ++i)
		// 	std::cout << i << ": " << match[i] << '\n';
		// std::cout << "Suffix: '" << match.suffix() << "\'\n\n";

		return true;
	}
	return false;
}

std::vector<std::string> regexp_strsplit(const std::string &string_to_split, const std::string &rgx_str) {
	std::vector<std::string> elems;

	std::regex rgx(rgx_str);
	std::sregex_token_iterator iter(string_to_split.begin(), string_to_split.end(), rgx, -1);
	std::sregex_token_iterator end;

	for (; iter != end; ++iter)
		elems.push_back(*iter);

	return elems;
}

std::string string_lucase(std::string s, const std::string &strcase) {
	if (strcase == "upper")
		std::transform(s.begin(), s.end(),s.begin(), ::toupper);
	
	if (strcase == "lower")
		std::transform(s.begin(), s.end(),s.begin(), ::tolower);
	
	return s;
}

std::string string_trim(std::string s, const std::string &chars_to_trim, const std::string &rltrim) {
	if (rltrim == "ltrim" || rltrim == "trim")
		s.erase(0, s.find_first_not_of(chars_to_trim));
	
	if (rltrim == "rtrim" || rltrim == "trim")
		s.erase(s.find_last_not_of(chars_to_trim)+1);

	return s;
}

std::string string_padd(const std::string &str, int pad_len, char fill_char, bool from_right) {
	int str_len = str.length();

	if (str_len == pad_len)
		return str;
	else if (str_len > pad_len) {
		return (from_right ? str.substr(0, pad_len) : str.substr(str_len - pad_len, std::string::npos));
	}

	if (from_right)
		return str + std::string(pad_len - str.size(), fill_char);
	else
		return std::string(pad_len - str.size(), fill_char) + str;
}


std::string string_substring(const std::string & str, long pos, long count) {
	size_t	start_pos = pos;

	if (pos < 0) {
		start_pos = str.size() - abs(pos);
	}
	
	if ( (start_pos >= str.size()) || (count < 1) || (start_pos < 0) ) {
		throw std::invalid_argument("Invalid parameter(s) for string-substr.");
	}

	return str.substr(start_pos, count);
}

size_t string_find_substr(const std::string & str, const std::string & pattern, long pos) {
	if (pos >= str.size()) {
		throw std::invalid_argument("Invalid parameter(s) for string-find.");
	}

	size_t p = str.find(pattern, pos);
	
	return p != str.npos ? p : -1;
}