#include "TypeMappings.h"
#include "catalog/PgTypeContainer.h"

//namespace {
//	using Fallbacks = std::unordered_map<Oid, Oid>;

//	Fallbacks fallbacks = {
//		{ oid_text, oid_varchar },
//		{ }
//	};
//}

TypeMappings::TypeMappings(std::shared_ptr<const PgTypeContainer> types)
	: m_types(types)
{}

TypeMappings::TypeMappings(std::shared_ptr<const PgTypeContainer> types, std::initializer_list<Mapping> mappings)
	: TypeMappings(types)
{
	m_typeMap.insert(mappings.begin(), mappings.end());
}

TypeMappingResult TypeMappings::getTypeForOid(Oid oid) const
{
	auto res = m_typeMap.find(oid);
	if (res != m_typeMap.end()) {
		QString dbtypename;
		if (m_types) {
			const PgType* type = m_types->getByKey(oid);
			if (type)
				dbtypename = type->objectName();
		}

		return { res->second, dbtypename };
	}

	if (m_types) {
		const PgType *type = m_types->getByKey(oid);
		// Found a valid type? elem is set? then it is array type
		if (type && type->elem != InvalidOid) {
			// Lookup what the element type is and wrap the mapping for that in the standard container type
			// for the language config. If that isn't right the end user should create a specific mapping for
			// that array type.
			res = m_typeMap.find(type->elem);
			const PgType *elem_type = m_types->getByKey(type->elem);
			QString type_string;
			if (res == m_typeMap.end()) {
				type_string = m_defaultStringType;
			}
			else {
				type_string = res->second;
			}
			return {
				QString(m_defaultContainerType).arg(type_string),
				elem_type->objectName() + "[]"
			};
		}
		else {
			return { m_defaultStringType, type->objectName() };
		}
	}
	// We shouldn't get here unless m_types is empty
	return { m_defaultStringType, QString() };
}

void TypeMappings::setTypes(std::shared_ptr<const PgTypeContainer> types)
{
	m_types = types;
}

void TypeMappings::setDefaultStringType(QString str)
{
	m_defaultStringType = str;
}

void TypeMappings::setDefaultContainerType(QString str)
{
	m_defaultContainerType = str;
}

void TypeMappings::set(Oid oid, QString type)
{
	m_typeMap.insert_or_assign(oid, type);
}



//constexpr Oid bool_oid = 16;
//constexpr Oid bytea_oid = 17;
//constexpr Oid char_oid = 18;
//constexpr Oid name_oid = 19;
//constexpr Oid int8_oid = 20;
//constexpr Oid int2_oid = 21;
//constexpr Oid int4_oid = 23;
//constexpr Oid regproc_oid = 24;
//constexpr Oid text_oid = 25;
//constexpr Oid oid_oid = 26;
//constexpr Oid tid_oid = 27;
//constexpr Oid xid_oid = 28;
//constexpr Oid cid_oid = 29;
//constexpr Oid json_oid = 114;
//constexpr Oid xml_oid = 142;
//constexpr Oid point_oid = 600;
//constexpr Oid lseg_oid = 601;
//constexpr Oid path_oid = 602;
//constexpr Oid box_oid = 603;
//constexpr Oid polygon_oid = 604;
//constexpr Oid line_oid = 628;
//constexpr Oid cidr_oid = 650;
//constexpr Oid float4_oid = 700;
//constexpr Oid float8_oid = 701;
//constexpr Oid abstime_oid = 702;
//constexpr Oid reltime_oid = 703;
//constexpr Oid tinterval_oid = 704;
//constexpr Oid circle_oid = 718;
//constexpr Oid money_oid = 790;
//constexpr Oid macaddr_oid = 829;
//constexpr Oid inet_oid = 869;
//constexpr Oid aclitem_oid = 1033;
//constexpr Oid bpchar_oid = 1042;
//constexpr Oid varchar_oid = 1043;
//constexpr Oid date_oid = 1082;
//constexpr Oid time_oid = 1083;
//constexpr Oid timestamp_oid = 1114;
//constexpr Oid timestamptz_oid = 1184;
//constexpr Oid interval_oid = 1186;
//constexpr Oid timetz_oid = 1266;
//constexpr Oid bit_oid = 1560;
//constexpr Oid varbit_oid = 1562;
//constexpr Oid numeric_oid = 1700;
//constexpr Oid refcursor_oid = 1790;
//constexpr Oid regprocedure_oid = 2202;
//constexpr Oid regoper_oid = 2203;
//constexpr Oid regoperator_oid = 2204;
//constexpr Oid regclass_oid = 2205;
//constexpr Oid regtype_oid = 2206;
//constexpr Oid uuid_oid = 2950;
//constexpr Oid txid_snapshot_oid = 2970;
//constexpr Oid pg_lsn_oid = 3220;
//constexpr Oid tsvector_oid = 3614;
//constexpr Oid tsquery_oid = 3615;
//constexpr Oid gtsvector_oid = 3642;
//constexpr Oid regconfig_oid = 3734;
//constexpr Oid regdictionary_oid = 3769;
//constexpr Oid jsonb_oid = 3802;
//constexpr Oid int4range_oid = 3904;
//constexpr Oid numrange_oid = 3906;
//constexpr Oid tsrange_oid = 3908;
//constexpr Oid tstzrange_oid = 3910;
//constexpr Oid daterange_oid = 3912;
//constexpr Oid int8range_oid = 3926;
//constexpr Oid regnamespace_oid = 4089;
//constexpr Oid regrole_oid = 4096;
