#include <uunit.h>

#include <util.h>

class ArgSplitTest
	: public uUnit
{
public:
	using fs = std::filesystem::path;

	ArgSplitTest()
	{
		uTEST(ArgSplitTest::plain_test);
		uTEST(ArgSplitTest::quot_test);
		uTEST(ArgSplitTest::apotrophe_test);
		uTEST(ArgSplitTest::mixed_test);
		uTEST(ArgSplitTest::escape_test);
	}

	void plain_test()
	{
		using namespace std::string_literals;

		{ // zero
			auto res = argsplit({});
			uASSERT_EQUAL(0u, res.size());
		}

		{ // one
			auto res = argsplit("hello"s);
			uASSERT_EQUAL(1u, res.size());
			uASSERT_EQUAL("hello"s, res[0]);
		}

		{ // many
			auto res = argsplit("hello world"s);
			uASSERT_EQUAL(2u, res.size());
			uASSERT_EQUAL("hello"s, res[0]);
			uASSERT_EQUAL("world"s, res[1]);
		}
	}

	void quot_test()
	{
		using namespace std::string_literals;

		{ // zero
			auto res = argsplit("\"\"");
			uASSERT_EQUAL(1u, res.size());
			uASSERT_EQUAL("\"\""s, res[0]);
		}

		{ // one
			auto res = argsplit("\"hello\""s);
			uASSERT_EQUAL(1u, res.size());
			uASSERT_EQUAL("\"hello\""s, res[0]);
		}

		{ // one with space
			auto res = argsplit("\"hel lo\""s);
			uASSERT_EQUAL(1u, res.size());
			uASSERT_EQUAL("\"hel lo\""s, res[0]);
		}

		{ // many
			auto res = argsplit("\"hello\" \"world\""s);
			uASSERT_EQUAL(2u, res.size());
			uASSERT_EQUAL("\"hello\""s, res[0]);
			uASSERT_EQUAL("\"world\""s, res[1]);
		}

		{ // many with spaces
			auto res = argsplit("\"hel lo\" \"wor ld\""s);
			uASSERT_EQUAL(2u, res.size());
			uASSERT_EQUAL("\"hel lo\""s, res[0]);
			uASSERT_EQUAL("\"wor ld\""s, res[1]);
		}
	}

	void apotrophe_test()
	{
		using namespace std::string_literals;

		{ // zero
			auto res = argsplit("\'\'");
			uASSERT_EQUAL(1u, res.size());
			uASSERT_EQUAL("\'\'"s, res[0]);
		}

		{ // one
			auto res = argsplit("\'hello\'"s);
			uASSERT_EQUAL(1u, res.size());
			uASSERT_EQUAL("\'hello\'"s, res[0]);
		}

		{ // one with space
			auto res = argsplit("\'hel lo\'"s);
			uASSERT_EQUAL(1u, res.size());
			uASSERT_EQUAL("\'hel lo\'"s, res[0]);
		}

		{ // many
			auto res = argsplit("\'hello\' \'world\'"s);
			uASSERT_EQUAL(2u, res.size());
			uASSERT_EQUAL("\'hello\'"s, res[0]);
			uASSERT_EQUAL("\'world\'"s, res[1]);
		}

		{ // many with spaces
			auto res = argsplit("\'hel lo\' \'wor ld\'"s);
			uASSERT_EQUAL(2u, res.size());
			uASSERT_EQUAL("\'hel lo\'"s, res[0]);
			uASSERT_EQUAL("\'wor ld\'"s, res[1]);
		}
	}

	void mixed_test()
	{
		using namespace std::string_literals;

		{ // zero
			auto res = argsplit("\'\'");
			uASSERT_EQUAL(1u, res.size());
			uASSERT_EQUAL("\'\'"s, res[0]);
		}

		{ // one
			auto res = argsplit("\'he\"llo\'"s);
			uASSERT_EQUAL(1u, res.size());
			uASSERT_EQUAL("\'he\"llo\'"s, res[0]);
		}

		{ // one
			auto res = argsplit("\"he\'llo\""s);
			uASSERT_EQUAL(1u, res.size());
			uASSERT_EQUAL("\"he\'llo\""s, res[0]);
		}

		{ // one with space
			auto res = argsplit("\'he\"l lo\'\""s);
			uASSERT_EQUAL(1u, res.size());
			uASSERT_EQUAL("\'he\"l lo\'\""s, res[0]);
		}

		{ // one with space
			auto res = argsplit("\"he\'l lo\"\'"s);
			uASSERT_EQUAL(1u, res.size());
			uASSERT_EQUAL("\"he\'l lo\"\'"s, res[0]);
		}

		{ // many
			auto res = argsplit("\"he\'llo\" \"wor\'ld\""s);
			uASSERT_EQUAL(2u, res.size());
			uASSERT_EQUAL("\"he\'llo\""s, res[0]);
			uASSERT_EQUAL("\"wor\'ld\""s, res[1]);
		}

		{ // many with spaces
			auto res = argsplit("\'hel\"lo\' \'wor\"ld\'"s);
			uASSERT_EQUAL(2u, res.size());
			uASSERT_EQUAL("\'hel\"lo\'"s, res[0]);
			uASSERT_EQUAL("\'wor\"ld\'"s, res[1]);
		}
	}

	void escape_test()
	{
		using namespace std::string_literals;

		{ // zero
			auto res = argsplit("\\");
			uASSERT_EQUAL(1u, res.size());
			uASSERT_EQUAL("\\"s, res[0]);
		}

		{ // one
			auto res = argsplit("\\\'"s);
			uASSERT_EQUAL(1u, res.size());
			uASSERT_EQUAL("\\\'"s, res[0]);
		}

		{ // one
			auto res = argsplit("\\\""s);
			uASSERT_EQUAL(1u, res.size());
			uASSERT_EQUAL("\\\""s, res[0]);
		}

		{ // one
			auto res = argsplit("\\\\"s);
			uASSERT_EQUAL(1u, res.size());
			uASSERT_EQUAL("\\\\"s, res[0]);
		}

		{ // one
			auto res = argsplit("a\\ b"s);
			uASSERT_EQUAL(1u, res.size());
			uASSERT_EQUAL("a\\ b"s, res[0]);
		}
	}
};

// Registers the fixture into the 'registry'
static ArgSplitTest test;