#include "DefaultConfigs.h"
#include "IndentationConfig.h"
#include "LanguageConfig.h"
#include "NameManglingRules.h"
#include "ResultLoopTemplate.h"
#include "StructureTemplate.h"
#include "TypeMappings.h"
#include "Pgsql_oids.h"
#include "catalog/PgDatabaseCatalog.h"

using namespace Pgsql;

class PgTypeContainer;

std::shared_ptr<const TypeMappings>  GetPglabCppTypeMappings(std::shared_ptr<const PgTypeContainer> types)
{
	auto tm = std::make_shared<TypeMappings>(types, std::initializer_list<TypeMappings::Mapping>
	{
		{ bool_oid, "bool" },
		{ char_oid, "char" },
		{ name_oid, "QString" },
		{ int8_oid, "int64_t" },
		{ int2_oid, "int16_t" },
		{ int4_oid, "int32_t" },
		{ text_oid, "QString" },
		{ oid_oid, "Oid" },
		{ float4_oid, "float" },
		{ float8_oid, "double" }
	});
	tm->setDefaultStringType("QString");
	tm->setDefaultContainerType("std::vector<%1>");
	return std::move(tm);
}

std::shared_ptr<StructureTemplate> buildPglabStructureTemplate()
{
	auto t = std::make_shared<StructureTemplate>();
	t->m_structTemplate =
R"__(class /%structname%/ {
public:
/%structfields%/
};
using /%structname%/Lst = std::vector</%structname%/>;
)__";

	t->m_fieldTemplate = "/%typename%/ /%varname%/; // /%dbtype%/";
	//st_templ->m_fieldSeparator;

	return t;
}

std::shared_ptr<ResultLoopTemplate> buildPglabResultLoopTemplate()
{
	auto t = std::make_shared<ResultLoopTemplate>();
	t->m_loopTemplate =
R"__(Pgsql::Result result = conn.query(/%queryliteral%/);
/%structname%/Lst lst;
for (auto row: result) {
	Pgsql::Col col(row);
	/%structname%/ v;
	col
	/%assignfields%/;
	lst.push_back(v);
}
)__";
	t->m_retrieveValueTemplate = " >> v./%varname%/";

	return t;
}


std::shared_ptr<LanguageConfig> buildPglabCppLanguageConfig(std::shared_ptr<PgDatabaseCatalog> catalog)
{
	auto config = std::make_shared<LanguageConfig>();
	config->setTypeMappings(GetPglabCppTypeMappings(catalog->types()));
	config->setNameManglingRules(std::make_shared<NameManglingRules>());
	config->setStructureTemplate(buildPglabStructureTemplate());
	config->setIndentationConfig(std::make_shared<IndentationConfig>());
	config->setResultLoopTemplate(buildPglabResultLoopTemplate());
	return config;
}


std::shared_ptr<const LanguageConfig> getPglabCppLanguageConfig(std::shared_ptr<PgDatabaseCatalog> catalog)
{
	static auto config = buildPglabCppLanguageConfig(catalog);
	return config;
}


