#include <drogon/drogon_test.h>
#include <drogon/utils/Utilities.h>
#include <string>

struct SameContent {
	SameContent(const std::vector<std::string> &container) :
			container_(container.begin(), container.end()) {
	}

	std::vector<std::string> container_;
};

template <typename Container1>
inline bool operator==(const Container1 &a, const SameContent &wrapper) {
	const auto &b = wrapper.container_;
	if (a.size() != b.size())
		return false;

	auto ait = a.begin();
	auto bit = b.begin();

	while (ait != a.end() && bit != b.end()) {
		if (*ait != *bit)
			break;
		ait++;
		bit++;
	}
	return ait == a.end() && bit == b.end();
}

using namespace drogon;
DROGON_TEST(StringOpsTest) {
	SUBSECTION(SplitString) {
		std::string str = "1,2,3,3,,4";
		CHECK(utils::splitString(str, ",") ==
				SameContent({ "1", "2", "3", "3", "4" }));
		CHECK(utils::splitString(str, ",", true) ==
				SameContent({ "1", "2", "3", "3", "", "4" }));
		CHECK(utils::splitString(str, "|", true) ==
				SameContent({ "1,2,3,3,,4" }));

		str = "a||b||c||||";
		CHECK(utils::splitString(str, "||") == SameContent({ "a", "b", "c" }));
		CHECK(utils::splitString(str, "||", true) ==
				SameContent({ "a", "b", "c", "", "" }));

		str = "aabbbaabbbb";
		CHECK(utils::splitString(str, "bb") == SameContent({ "aa", "baa" }));
		CHECK(utils::splitString(str, "bb", true) ==
				SameContent({ "aa", "baa", "", "" }));

		str = "";
		CHECK(utils::splitString(str, ",") == SameContent({}));
		CHECK(utils::splitString(str, ",", true) == SameContent({ "" }));
	}

	SUBSECTION(SplitStringToSet) {
		// splitStringToSet ignores empty strings
		std::string str = "1,2,3,3,,4";
		auto s = utils::splitStringToSet(str, ",");
		CHECK(s.size() == 4UL);
		CHECK(s.count("1") == 1UL);
		CHECK(s.count("2") == 1UL);
		CHECK(s.count("3") == 1UL);
		CHECK(s.count("4") == 1UL);

		str = "a|||a";
		s = utils::splitStringToSet(str, "||");
		CHECK(s.size() == 2UL);
		CHECK(s.count("a") == 1UL);
		CHECK(s.count("|a") == 1UL);
	}

	SUBSECTION(ReplaceAll) {
		std::string str = "3.14159";
		utils::replaceAll(str, "1", "a");
		CHECK(str == "3.a4a59");

		str = "aaxxxaaxxxxaaxxxxx";
		utils::replaceAll(str, "xx", "oo");
		CHECK(str == "aaooxaaooooaaoooox");
	}
}
