#include <gtest/gtest.h>
#include <gmock/gmock-matchers.h>
#include "PrintTo_Qt.h"
#include <QRegularExpression>
#include "catalog/PgType.h"
#include "catalog/PgTypeContainer.h"
#include "codebuilder/IndentationConfig.h"
#include "codebuilder/TypeMappings.h"
#include "Pgsql_oids.h"

using namespace testing;



// Test to verify my understanding of the documentation
TEST(QRegularExpression, doIUnderstandItCorrectly)
{
	QString text("abcdefghi");
	QRegularExpression re("c(def)g");
	QRegularExpressionMatch match;
	int pos = text.indexOf(re, 0, &match);

	ASSERT_THAT(pos, Eq(2));
	ASSERT_THAT(match.capturedStart(), Eq(2));
	ASSERT_THAT(match.capturedEnd(), Eq(7));
	ASSERT_THAT(match.capturedStart(1), Eq(3));
	ASSERT_THAT(match.capturedEnd(1), Eq(6));
}

TEST(QRegularExpression, doIUnderstandItCorrectly2)
{
	QString text("abc/%def%/ghi");
	QRegularExpression re("(?:[^\\\\]|^)(\\/%([a-zA-Z0-9_-]+)%\\/)");
	QRegularExpressionMatch match;
	int pos = text.indexOf(re, 0, &match);

	ASSERT_THAT(pos, Eq(2));
	ASSERT_THAT(match.capturedStart(1), Eq(3));
	ASSERT_THAT(match.capturedLength(1), Eq(7));
	ASSERT_THAT(match.capturedStart(2), Eq(5));
	ASSERT_THAT(match.capturedLength(2), Eq(3));
}

#include <QTextStream>

void FormatToStream(QTextStream &stream, QString format, std::function<void(QTextStream &, QString)> field_callback);

TEST(FormatToStream, EmptyFormat)
{
	QString result;
	QTextStream stream(&result);
	FormatToStream(stream, "", nullptr);
	stream.flush();

	ASSERT_THAT(result, Eq(QString()));
}

TEST(FormatToStream, OnlyVar)
{
	QString result;
	QTextStream stream(&result);
	FormatToStream(stream, "/%var%/",
		[](QTextStream &stream, QString varname)
		{
			if (varname == "var")
				stream << "abc";
		});
	stream.flush();

	ASSERT_EQ(result, QString("abc"));
}

TEST(FormatToStream, StartWithVar)
{
	QString result;
	QTextStream stream(&result);
	FormatToStream(stream, "/%var%/def",
		[](QTextStream &stream, QString varname)
		{
			if (varname == "var")
				stream << "abc";
		});
	stream.flush();

	ASSERT_EQ(result, QString("abcdef"));
}

TEST(FormatToStream, EndWithVar)
{
	QString result;
	QTextStream stream(&result);
	FormatToStream(stream, "def/%var%/",
		[](QTextStream &stream, QString varname)
		{
			if (varname == "var")
				stream << "abc";
		});
	stream.flush();

	ASSERT_EQ(result, QString("defabc"));
}

TEST(FormatToStream, TwoVarsTogether)
{
	QString result;
	QTextStream stream(&result);
	FormatToStream(stream, "/%var1%//%var2%/",
		[](QTextStream &stream, QString varname)
		{
			if (varname == "var1")
				stream << "abc";
			else if (varname == "var2")
				stream << "def";
		});
	stream.flush();

	ASSERT_EQ(result, QString("abcdef"));
}

TEST(FormatToStream, TwoVarsWithTextInBetween)
{
	QString result;
	QTextStream stream(&result);
	FormatToStream(stream, "1/%var1%/2/%var2%/3",
		[](QTextStream &stream, QString varname)
		{
			if (varname == "var1")
				stream << "abc";
			else if (varname == "var2")
				stream << "def";
		});
	stream.flush();

	ASSERT_EQ(result, QString("1abc2def3"));
}


TEST(IndentationConfig, tab8indent4true_level1)
{
	IndentationConfig icfg(8, 4, true);
	QString result = icfg.getIndentString(1);
	ASSERT_EQ(result, "    ");
}

TEST(IndentationConfig, tab8indent4true_level2)
{
	IndentationConfig icfg(8, 4, true);
	QString result = icfg.getIndentString(2);
	ASSERT_EQ(result, "\t");
}

TEST(IndentationConfig, tab8indent4true_level3)
{
	IndentationConfig icfg(8, 4, true);
	QString result = icfg.getIndentString(3);
	ASSERT_EQ(result, "\t    ");
}

TEST(IndentationConfig, tab8indent4false_level1)
{
	IndentationConfig icfg(8, 4, false);
	QString result = icfg.getIndentString(1);
	ASSERT_EQ(result, "    ");
}

TEST(IndentationConfig, tab8indent4false_level2)
{
	IndentationConfig icfg(8, 4, false);
	QString result = icfg.getIndentString(2);
	ASSERT_EQ(result, "        ");
}

