#include "base/exception.hpp"
#include "base/objectlock.hpp"
#include "base/utility.hpp"
#include "base/convert.hpp"
#include "base/debug.hpp"
#include "base/dependencygraph.hpp"
#include "base/logger.hpp"
#include "base/function.hpp"
#include "base/configobject.hpp"
#include "base/configtype.hpp"
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
#pragma GCC diagnostic ignored "-Wunused-variable"
namespace icinga
{

TypeImpl<Influxdb2Writer>::TypeImpl()
{ }

TypeImpl<Influxdb2Writer>::~TypeImpl()
{ }

String TypeImpl<Influxdb2Writer>::GetName() const
{
	return "Influxdb2Writer";
}

int TypeImpl<Influxdb2Writer>::GetAttributes() const
{
	return 0;
}

Type::Ptr TypeImpl<Influxdb2Writer>::GetBaseType() const
{
	return InfluxdbCommonWriter::TypeInstance;
}

int TypeImpl<Influxdb2Writer>::GetFieldId(const String& name) const
{
	int offset = InfluxdbCommonWriter::TypeInstance->GetFieldCount();

	switch (static_cast<int>(Utility::SDBM(name, 1))) {
		case 97:
			if (name == "auth_token")
				return offset + 2;

			break;
		case 98:
			if (name == "bucket")
				return offset + 1;

			break;
		case 111:
			if (name == "organization")
				return offset + 0;

			break;
	}

	return InfluxdbCommonWriter::TypeInstance->GetFieldId(name);
}

Field TypeImpl<Influxdb2Writer>::GetFieldInfo(int id) const
{
	int real_id = id - InfluxdbCommonWriter::TypeInstance->GetFieldCount();
	if (real_id < 0) { return InfluxdbCommonWriter::TypeInstance->GetFieldInfo(id); }
	switch (real_id) {
		case 0:
			return {0, "String", "organization", "organization", nullptr, 258, 0};
		case 1:
			return {1, "String", "bucket", "bucket", nullptr, 258, 0};
		case 2:
			return {2, "String", "auth_token", "auth_token", nullptr, 2306, 0};
		default:
			throw std::runtime_error("Invalid field ID.");
	}
}

int TypeImpl<Influxdb2Writer>::GetFieldCount() const
{
	return 3 + InfluxdbCommonWriter::TypeInstance->GetFieldCount();
}

ObjectFactory TypeImpl<Influxdb2Writer>::GetFactory() const
{
	return TypeHelper<Influxdb2Writer, false>::GetFactory();
}

int TypeImpl<Influxdb2Writer>::GetActivationPriority() const
{
	return 100;
}

void TypeImpl<Influxdb2Writer>::RegisterAttributeHandler(int fieldId, const Type::AttributeHandler& callback)
{
	int real_id = fieldId - InfluxdbCommonWriter::TypeInstance->GetFieldCount(); 
	if (real_id < 0) { InfluxdbCommonWriter::TypeInstance->RegisterAttributeHandler(fieldId, callback); return; }
	switch (real_id) {
		case 0:
			ObjectImpl<Influxdb2Writer>::OnOrganizationChanged.connect(callback);
			break;
		case 1:
			ObjectImpl<Influxdb2Writer>::OnBucketChanged.connect(callback);
			break;
		case 2:
			ObjectImpl<Influxdb2Writer>::OnAuthTokenChanged.connect(callback);
			break;
		default:
			throw std::runtime_error("Invalid field ID.");
	}
}

void ObjectImpl<Influxdb2Writer>::Validate(int types, const ValidationUtils& utils)
{
	InfluxdbCommonWriter::Validate(types, utils);

	if (2 & types)
		ValidateOrganization(Lazy<String>([this]() { return GetOrganization(); }), utils);
	if (2 & types)
		ValidateBucket(Lazy<String>([this]() { return GetBucket(); }), utils);
	if (2 & types)
		ValidateAuthToken(Lazy<String>([this]() { return GetAuthToken(); }), utils);
}

void ObjectImpl<Influxdb2Writer>::SimpleValidateOrganization(const Lazy<String>& value, const ValidationUtils& utils)
{
	if (value().IsEmpty())
		BOOST_THROW_EXCEPTION(ValidationError(dynamic_cast<ConfigObject *>(this), { "organization" }, "Attribute must not be empty."));

}

void ObjectImpl<Influxdb2Writer>::SimpleValidateBucket(const Lazy<String>& value, const ValidationUtils& utils)
{
	if (value().IsEmpty())
		BOOST_THROW_EXCEPTION(ValidationError(dynamic_cast<ConfigObject *>(this), { "bucket" }, "Attribute must not be empty."));

}

void ObjectImpl<Influxdb2Writer>::SimpleValidateAuthToken(const Lazy<String>& value, const ValidationUtils& utils)
{
	if (value().IsEmpty())
		BOOST_THROW_EXCEPTION(ValidationError(dynamic_cast<ConfigObject *>(this), { "auth_token" }, "Attribute must not be empty."));

}

ObjectImpl<Influxdb2Writer>::ObjectImpl()
{
	SetOrganization(GetDefaultOrganization(), true);
	SetBucket(GetDefaultBucket(), true);
	SetAuthToken(GetDefaultAuthToken(), true);
}

ObjectImpl<Influxdb2Writer>::~ObjectImpl()
{ }

void ObjectImpl<Influxdb2Writer>::SetField(int id, const Value& value, bool suppress_events, const Value& cookie)
{
	int real_id = id - InfluxdbCommonWriter::TypeInstance->GetFieldCount(); 
	if (real_id < 0) { InfluxdbCommonWriter::SetField(id, value, suppress_events, cookie); return; }
	switch (real_id) {
		case 0:
			SetOrganization(value, suppress_events, cookie);
			break;
		case 1:
			SetBucket(value, suppress_events, cookie);
			break;
		case 2:
			SetAuthToken(value, suppress_events, cookie);
			break;
		default:
			throw std::runtime_error("Invalid field ID.");
	}
}

Value ObjectImpl<Influxdb2Writer>::GetField(int id) const
{
	int real_id = id - InfluxdbCommonWriter::TypeInstance->GetFieldCount(); 
	if (real_id < 0) { return InfluxdbCommonWriter::GetField(id); }
	switch (real_id) {
		case 0:
			return GetOrganization();
		case 1:
			return GetBucket();
		case 2:
			return GetAuthToken();
		default:
			throw std::runtime_error("Invalid field ID.");
	}
}

void ObjectImpl<Influxdb2Writer>::ValidateField(int id, const Lazy<Value>& lvalue, const ValidationUtils& utils)
{
	int real_id = id - InfluxdbCommonWriter::TypeInstance->GetFieldCount(); 
	if (real_id < 0) { InfluxdbCommonWriter::ValidateField(id, lvalue, utils); return; }
	switch (real_id) {
		case 0:
			ValidateOrganization(lvalue, utils);
			break;
		case 1:
			ValidateBucket(lvalue, utils);
			break;
		case 2:
			ValidateAuthToken(lvalue, utils);
			break;
		default:
			throw std::runtime_error("Invalid field ID.");
	}
}

void ObjectImpl<Influxdb2Writer>::NotifyField(int id, const Value& cookie)
{
	int real_id = id - InfluxdbCommonWriter::TypeInstance->GetFieldCount(); 
	if (real_id < 0) { InfluxdbCommonWriter::NotifyField(id, cookie); return; }
	switch (real_id) {
		case 0:
			NotifyOrganization(cookie);
			break;
		case 1:
			NotifyBucket(cookie);
			break;
		case 2:
			NotifyAuthToken(cookie);
			break;
		default:
			throw std::runtime_error("Invalid field ID.");
	}
}

Object::Ptr ObjectImpl<Influxdb2Writer>::NavigateField(int id) const
{
	int real_id = id - InfluxdbCommonWriter::TypeInstance->GetFieldCount(); 
	if (real_id < 0) { return InfluxdbCommonWriter::NavigateField(id); }
	throw std::runtime_error("Invalid field ID.");
}

String ObjectImpl<Influxdb2Writer>::GetOrganization() const
{
	return m_Organization.load();
}

String ObjectImpl<Influxdb2Writer>::GetBucket() const
{
	return m_Bucket.load();
}

String ObjectImpl<Influxdb2Writer>::GetAuthToken() const
{
	return m_AuthToken.load();
}

void ObjectImpl<Influxdb2Writer>::SetOrganization(const String& value, bool suppress_events, const Value& cookie)
{
	m_Organization.store(value);
	if (!suppress_events) {
		NotifyOrganization(cookie);
	}

}

void ObjectImpl<Influxdb2Writer>::SetBucket(const String& value, bool suppress_events, const Value& cookie)
{
	m_Bucket.store(value);
	if (!suppress_events) {
		NotifyBucket(cookie);
	}

}

void ObjectImpl<Influxdb2Writer>::SetAuthToken(const String& value, bool suppress_events, const Value& cookie)
{
	m_AuthToken.store(value);
	if (!suppress_events) {
		NotifyAuthToken(cookie);
	}

}

void ObjectImpl<Influxdb2Writer>::NotifyOrganization(const Value& cookie)
{
	auto *dobj = dynamic_cast<ConfigObject *>(this);
	if (!dobj || dobj->IsActive())
		OnOrganizationChanged(static_cast<Influxdb2Writer *>(this), cookie);
}

void ObjectImpl<Influxdb2Writer>::NotifyBucket(const Value& cookie)
{
	auto *dobj = dynamic_cast<ConfigObject *>(this);
	if (!dobj || dobj->IsActive())
		OnBucketChanged(static_cast<Influxdb2Writer *>(this), cookie);
}

void ObjectImpl<Influxdb2Writer>::NotifyAuthToken(const Value& cookie)
{
	auto *dobj = dynamic_cast<ConfigObject *>(this);
	if (!dobj || dobj->IsActive())
		OnAuthTokenChanged(static_cast<Influxdb2Writer *>(this), cookie);
}

String ObjectImpl<Influxdb2Writer>::GetDefaultOrganization() const
{
	return String();
}

String ObjectImpl<Influxdb2Writer>::GetDefaultBucket() const
{
	return String();
}

String ObjectImpl<Influxdb2Writer>::GetDefaultAuthToken() const
{
	return String();
}


boost::signals2::signal<void (const intrusive_ptr<Influxdb2Writer>&, const Value&)> ObjectImpl<Influxdb2Writer>::OnOrganizationChanged;


boost::signals2::signal<void (const intrusive_ptr<Influxdb2Writer>&, const Value&)> ObjectImpl<Influxdb2Writer>::OnBucketChanged;


boost::signals2::signal<void (const intrusive_ptr<Influxdb2Writer>&, const Value&)> ObjectImpl<Influxdb2Writer>::OnAuthTokenChanged;

void ObjectImpl<Influxdb2Writer>::ValidateAuthToken(const Lazy<String>& lvalue, const ValidationUtils& utils)
{
	SimpleValidateAuthToken(lvalue, utils);
}

void ObjectImpl<Influxdb2Writer>::ValidateBucket(const Lazy<String>& lvalue, const ValidationUtils& utils)
{
	SimpleValidateBucket(lvalue, utils);
}

void ObjectImpl<Influxdb2Writer>::ValidateOrganization(const Lazy<String>& lvalue, const ValidationUtils& utils)
{
	SimpleValidateOrganization(lvalue, utils);
}

}
#pragma GCC diagnostic pop
