#include <gtest/gtest.h>
#include <gmock/gmock-matchers.h>
#include "ArrayParser.h"
#include "PrintTo_Qt.h"

using namespace testing;
using namespace Pgsql;

TEST(ArrayParser, emptyInput)
{
	const char * input = "";
	ArrayParser parser(input, -1);
	auto res = parser.GetNextElem();
	ASSERT_FALSE(res.ok);
}

TEST(ArrayParser, emptyArray)
{
	const char * input = "{}";
	ArrayParser parser(input, -1);
	auto res = parser.GetNextElem();
	ASSERT_FALSE(res.ok);
}

TEST(ArrayParser, oneInt)
{
	const char * input = "{1}";
	ArrayParser parser(input, -1);
	auto res = parser.GetNextElem();
	ASSERT_TRUE(res.ok);
	ASSERT_EQ(res.value, "1");

	res = parser.GetNextElem();
	ASSERT_FALSE(res.ok);
}

TEST(ArrayParser, twoElems)
{
	const char * input = "{1,2.3}";
	ArrayParser parser(input, -1);

	auto res = parser.GetNextElem();
	ASSERT_TRUE(res.ok);
	ASSERT_EQ(res.value, "1");

	res = parser.GetNextElem();
	ASSERT_TRUE(res.ok);
	ASSERT_EQ(res.value, "2.3");

	res = parser.GetNextElem();
	ASSERT_FALSE(res.ok);
}

TEST(ArrayParser, nullElem)
{
	const char * input = "{NULL}";
	ArrayParser parser(input, -1);
	auto res = parser.GetNextElem();
	ASSERT_TRUE(res.ok);
	ASSERT_EQ(res.value, std::nullopt);

	res = parser.GetNextElem();
	ASSERT_FALSE(res.ok);
}



// ARRAY['ab c', NULL, 'def', 'd"e', 'g''h ', 'g,j']
// {"ab c",NULL,def,"d\"e","g'h ","g,j"}

TEST(ArrayParser, quotedValues)
{
	const char * input = R"_({"ab c","de\"f"})_";
	ArrayParser parser(input, -1);
	auto res = parser.GetNextElem();
	ASSERT_TRUE(res.ok);
	ASSERT_EQ(res.value, "ab c");

	res = parser.GetNextElem();
	ASSERT_TRUE(res.ok);
	ASSERT_EQ(res.value, "de\"f");

	res = parser.GetNextElem();
	ASSERT_FALSE(res.ok);
}

TEST(ArrayParser, unexpectedEndWithNullTerminator)
{
	const char * input = "{abc";
	ArrayParser parser(input, -1);
	ASSERT_THROW(parser.GetNextElem(), std::runtime_error);
}

TEST(ArrayParser, unexpectedEndWithoutNullTerminator)
{
	const char * input = "{abc";
	ArrayParser parser(input, 3); // 3 will put c past the end
	ASSERT_THROW(parser.GetNextElem(), std::runtime_error);
}

// ARRAY['2017-12-11'::date, NULL]
// {2017-12-11,NULL}

// NULL::int2
// null
