#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<PerfdataWriter>::TypeImpl()
{ }

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

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

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

Type::Ptr TypeImpl<PerfdataWriter>::GetBaseType() const
{
	return ConfigObject::TypeInstance;
}

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

	switch (static_cast<int>(Utility::SDBM(name, 1))) {
		case 101:
			if (name == "enable_ha")
				return offset + 7;

			break;
		case 104:
			if (name == "host_perfdata_path")
				return offset + 0;
			if (name == "host_temp_path")
				return offset + 2;
			if (name == "host_format_template")
				return offset + 4;

			break;
		case 114:
			if (name == "rotation_interval")
				return offset + 6;

			break;
		case 115:
			if (name == "service_perfdata_path")
				return offset + 1;
			if (name == "service_temp_path")
				return offset + 3;
			if (name == "service_format_template")
				return offset + 5;

			break;
	}

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

Field TypeImpl<PerfdataWriter>::GetFieldInfo(int id) const
{
	int real_id = id - ConfigObject::TypeInstance->GetFieldCount();
	if (real_id < 0) { return ConfigObject::TypeInstance->GetFieldInfo(id); }
	switch (real_id) {
		case 0:
			return {0, "String", "host_perfdata_path", "host_perfdata_path", nullptr, 2, 0};
		case 1:
			return {1, "String", "service_perfdata_path", "service_perfdata_path", nullptr, 2, 0};
		case 2:
			return {2, "String", "host_temp_path", "host_temp_path", nullptr, 2, 0};
		case 3:
			return {3, "String", "service_temp_path", "service_temp_path", nullptr, 2, 0};
		case 4:
			return {4, "String", "host_format_template", "host_format_template", nullptr, 2, 0};
		case 5:
			return {5, "String", "service_format_template", "service_format_template", nullptr, 2, 0};
		case 6:
			return {6, "Number", "rotation_interval", "rotation_interval", nullptr, 2, 0};
		case 7:
			return {7, "Boolean", "enable_ha", "enable_ha", nullptr, 2, 0};
		default:
			throw std::runtime_error("Invalid field ID.");
	}
}

int TypeImpl<PerfdataWriter>::GetFieldCount() const
{
	return 8 + ConfigObject::TypeInstance->GetFieldCount();
}

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

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

void TypeImpl<PerfdataWriter>::RegisterAttributeHandler(int fieldId, const Type::AttributeHandler& callback)
{
	int real_id = fieldId - ConfigObject::TypeInstance->GetFieldCount(); 
	if (real_id < 0) { ConfigObject::TypeInstance->RegisterAttributeHandler(fieldId, callback); return; }
	switch (real_id) {
		case 0:
			ObjectImpl<PerfdataWriter>::OnHostPerfdataPathChanged.connect(callback);
			break;
		case 1:
			ObjectImpl<PerfdataWriter>::OnServicePerfdataPathChanged.connect(callback);
			break;
		case 2:
			ObjectImpl<PerfdataWriter>::OnHostTempPathChanged.connect(callback);
			break;
		case 3:
			ObjectImpl<PerfdataWriter>::OnServiceTempPathChanged.connect(callback);
			break;
		case 4:
			ObjectImpl<PerfdataWriter>::OnHostFormatTemplateChanged.connect(callback);
			break;
		case 5:
			ObjectImpl<PerfdataWriter>::OnServiceFormatTemplateChanged.connect(callback);
			break;
		case 6:
			ObjectImpl<PerfdataWriter>::OnRotationIntervalChanged.connect(callback);
			break;
		case 7:
			ObjectImpl<PerfdataWriter>::OnEnableHaChanged.connect(callback);
			break;
		default:
			throw std::runtime_error("Invalid field ID.");
	}
}

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

	if (2 & types)
		ValidateHostPerfdataPath(Lazy<String>([this]() { return GetHostPerfdataPath(); }), utils);
	if (2 & types)
		ValidateServicePerfdataPath(Lazy<String>([this]() { return GetServicePerfdataPath(); }), utils);
	if (2 & types)
		ValidateHostTempPath(Lazy<String>([this]() { return GetHostTempPath(); }), utils);
	if (2 & types)
		ValidateServiceTempPath(Lazy<String>([this]() { return GetServiceTempPath(); }), utils);
	if (2 & types)
		ValidateHostFormatTemplate(Lazy<String>([this]() { return GetHostFormatTemplate(); }), utils);
	if (2 & types)
		ValidateServiceFormatTemplate(Lazy<String>([this]() { return GetServiceFormatTemplate(); }), utils);
	if (2 & types)
		ValidateRotationInterval(Lazy<double>([this]() { return GetRotationInterval(); }), utils);
	if (2 & types)
		ValidateEnableHa(Lazy<bool>([this]() { return GetEnableHa(); }), utils);
}

void ObjectImpl<PerfdataWriter>::SimpleValidateHostPerfdataPath(const Lazy<String>& value, const ValidationUtils& utils)
{
}

void ObjectImpl<PerfdataWriter>::SimpleValidateServicePerfdataPath(const Lazy<String>& value, const ValidationUtils& utils)
{
}

void ObjectImpl<PerfdataWriter>::SimpleValidateHostTempPath(const Lazy<String>& value, const ValidationUtils& utils)
{
}

void ObjectImpl<PerfdataWriter>::SimpleValidateServiceTempPath(const Lazy<String>& value, const ValidationUtils& utils)
{
}

void ObjectImpl<PerfdataWriter>::SimpleValidateHostFormatTemplate(const Lazy<String>& value, const ValidationUtils& utils)
{
}

void ObjectImpl<PerfdataWriter>::SimpleValidateServiceFormatTemplate(const Lazy<String>& value, const ValidationUtils& utils)
{
}

void ObjectImpl<PerfdataWriter>::SimpleValidateRotationInterval(const Lazy<double>& value, const ValidationUtils& utils)
{
}

void ObjectImpl<PerfdataWriter>::SimpleValidateEnableHa(const Lazy<bool>& value, const ValidationUtils& utils)
{
}

ObjectImpl<PerfdataWriter>::ObjectImpl()
{
	SetHostPerfdataPath(GetDefaultHostPerfdataPath(), true);
	SetServicePerfdataPath(GetDefaultServicePerfdataPath(), true);
	SetHostTempPath(GetDefaultHostTempPath(), true);
	SetServiceTempPath(GetDefaultServiceTempPath(), true);
	SetHostFormatTemplate(GetDefaultHostFormatTemplate(), true);
	SetServiceFormatTemplate(GetDefaultServiceFormatTemplate(), true);
	SetRotationInterval(GetDefaultRotationInterval(), true);
	SetEnableHa(GetDefaultEnableHa(), true);
}

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

void ObjectImpl<PerfdataWriter>::SetField(int id, const Value& value, bool suppress_events, const Value& cookie)
{
	int real_id = id - ConfigObject::TypeInstance->GetFieldCount(); 
	if (real_id < 0) { ConfigObject::SetField(id, value, suppress_events, cookie); return; }
	switch (real_id) {
		case 0:
			SetHostPerfdataPath(value, suppress_events, cookie);
			break;
		case 1:
			SetServicePerfdataPath(value, suppress_events, cookie);
			break;
		case 2:
			SetHostTempPath(value, suppress_events, cookie);
			break;
		case 3:
			SetServiceTempPath(value, suppress_events, cookie);
			break;
		case 4:
			SetHostFormatTemplate(value, suppress_events, cookie);
			break;
		case 5:
			SetServiceFormatTemplate(value, suppress_events, cookie);
			break;
		case 6:
			SetRotationInterval(value, suppress_events, cookie);
			break;
		case 7:
			SetEnableHa(value, suppress_events, cookie);
			break;
		default:
			throw std::runtime_error("Invalid field ID.");
	}
}

Value ObjectImpl<PerfdataWriter>::GetField(int id) const
{
	int real_id = id - ConfigObject::TypeInstance->GetFieldCount(); 
	if (real_id < 0) { return ConfigObject::GetField(id); }
	switch (real_id) {
		case 0:
			return GetHostPerfdataPath();
		case 1:
			return GetServicePerfdataPath();
		case 2:
			return GetHostTempPath();
		case 3:
			return GetServiceTempPath();
		case 4:
			return GetHostFormatTemplate();
		case 5:
			return GetServiceFormatTemplate();
		case 6:
			return GetRotationInterval();
		case 7:
			return GetEnableHa();
		default:
			throw std::runtime_error("Invalid field ID.");
	}
}

void ObjectImpl<PerfdataWriter>::ValidateField(int id, const Lazy<Value>& lvalue, const ValidationUtils& utils)
{
	int real_id = id - ConfigObject::TypeInstance->GetFieldCount(); 
	if (real_id < 0) { ConfigObject::ValidateField(id, lvalue, utils); return; }
	switch (real_id) {
		case 0:
			ValidateHostPerfdataPath(lvalue, utils);
			break;
		case 1:
			ValidateServicePerfdataPath(lvalue, utils);
			break;
		case 2:
			ValidateHostTempPath(lvalue, utils);
			break;
		case 3:
			ValidateServiceTempPath(lvalue, utils);
			break;
		case 4:
			ValidateHostFormatTemplate(lvalue, utils);
			break;
		case 5:
			ValidateServiceFormatTemplate(lvalue, utils);
			break;
		case 6:
			ValidateRotationInterval(lvalue, utils);
			break;
		case 7:
			ValidateEnableHa(lvalue, utils);
			break;
		default:
			throw std::runtime_error("Invalid field ID.");
	}
}

void ObjectImpl<PerfdataWriter>::NotifyField(int id, const Value& cookie)
{
	int real_id = id - ConfigObject::TypeInstance->GetFieldCount(); 
	if (real_id < 0) { ConfigObject::NotifyField(id, cookie); return; }
	switch (real_id) {
		case 0:
			NotifyHostPerfdataPath(cookie);
			break;
		case 1:
			NotifyServicePerfdataPath(cookie);
			break;
		case 2:
			NotifyHostTempPath(cookie);
			break;
		case 3:
			NotifyServiceTempPath(cookie);
			break;
		case 4:
			NotifyHostFormatTemplate(cookie);
			break;
		case 5:
			NotifyServiceFormatTemplate(cookie);
			break;
		case 6:
			NotifyRotationInterval(cookie);
			break;
		case 7:
			NotifyEnableHa(cookie);
			break;
		default:
			throw std::runtime_error("Invalid field ID.");
	}
}

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

String ObjectImpl<PerfdataWriter>::GetHostPerfdataPath() const
{
	return m_HostPerfdataPath.load();
}

String ObjectImpl<PerfdataWriter>::GetServicePerfdataPath() const
{
	return m_ServicePerfdataPath.load();
}

String ObjectImpl<PerfdataWriter>::GetHostTempPath() const
{
	return m_HostTempPath.load();
}

String ObjectImpl<PerfdataWriter>::GetServiceTempPath() const
{
	return m_ServiceTempPath.load();
}

String ObjectImpl<PerfdataWriter>::GetHostFormatTemplate() const
{
	return m_HostFormatTemplate.load();
}

String ObjectImpl<PerfdataWriter>::GetServiceFormatTemplate() const
{
	return m_ServiceFormatTemplate.load();
}

double ObjectImpl<PerfdataWriter>::GetRotationInterval() const
{
	return m_RotationInterval.load();
}

bool ObjectImpl<PerfdataWriter>::GetEnableHa() const
{
	return m_EnableHa.load();
}

void ObjectImpl<PerfdataWriter>::SetHostPerfdataPath(const String& value, bool suppress_events, const Value& cookie)
{
	m_HostPerfdataPath.store(value);
	if (!suppress_events) {
		NotifyHostPerfdataPath(cookie);
	}

}

void ObjectImpl<PerfdataWriter>::SetServicePerfdataPath(const String& value, bool suppress_events, const Value& cookie)
{
	m_ServicePerfdataPath.store(value);
	if (!suppress_events) {
		NotifyServicePerfdataPath(cookie);
	}

}

void ObjectImpl<PerfdataWriter>::SetHostTempPath(const String& value, bool suppress_events, const Value& cookie)
{
	m_HostTempPath.store(value);
	if (!suppress_events) {
		NotifyHostTempPath(cookie);
	}

}

void ObjectImpl<PerfdataWriter>::SetServiceTempPath(const String& value, bool suppress_events, const Value& cookie)
{
	m_ServiceTempPath.store(value);
	if (!suppress_events) {
		NotifyServiceTempPath(cookie);
	}

}

void ObjectImpl<PerfdataWriter>::SetHostFormatTemplate(const String& value, bool suppress_events, const Value& cookie)
{
	m_HostFormatTemplate.store(value);
	if (!suppress_events) {
		NotifyHostFormatTemplate(cookie);
	}

}

void ObjectImpl<PerfdataWriter>::SetServiceFormatTemplate(const String& value, bool suppress_events, const Value& cookie)
{
	m_ServiceFormatTemplate.store(value);
	if (!suppress_events) {
		NotifyServiceFormatTemplate(cookie);
	}

}

void ObjectImpl<PerfdataWriter>::SetRotationInterval(double value, bool suppress_events, const Value& cookie)
{
	m_RotationInterval.store(value);
	if (!suppress_events) {
		NotifyRotationInterval(cookie);
	}

}

void ObjectImpl<PerfdataWriter>::SetEnableHa(bool value, bool suppress_events, const Value& cookie)
{
	m_EnableHa.store(value);
	if (!suppress_events) {
		NotifyEnableHa(cookie);
	}

}

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

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

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

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

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

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

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

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

String ObjectImpl<PerfdataWriter>::GetDefaultHostPerfdataPath() const
{
	 return Configuration::SpoolDir + "/perfdata/host-perfdata"; 
}

String ObjectImpl<PerfdataWriter>::GetDefaultServicePerfdataPath() const
{
	 return Configuration::SpoolDir + "/perfdata/service-perfdata"; 
}

String ObjectImpl<PerfdataWriter>::GetDefaultHostTempPath() const
{
	 return Configuration::SpoolDir + "/tmp/host-perfdata"; 
}

String ObjectImpl<PerfdataWriter>::GetDefaultServiceTempPath() const
{
	 return Configuration::SpoolDir + "/tmp/service-perfdata"; 
}

String ObjectImpl<PerfdataWriter>::GetDefaultHostFormatTemplate() const
{
	
			return "DATATYPE::HOSTPERFDATA\t"
				"TIMET::$host.last_check$\t"
				"HOSTNAME::$host.name$\t"
				"HOSTPERFDATA::$host.perfdata$\t"
				"HOSTCHECKCOMMAND::$host.check_command$\t"
				"HOSTSTATE::$host.state$\t"
				"HOSTSTATETYPE::$host.state_type$";
		
}

String ObjectImpl<PerfdataWriter>::GetDefaultServiceFormatTemplate() const
{
	
			return "DATATYPE::SERVICEPERFDATA\t"
				"TIMET::$service.last_check$\t"
				"HOSTNAME::$host.name$\t"
				"SERVICEDESC::$service.name$\t"
				"SERVICEPERFDATA::$service.perfdata$\t"
				"SERVICECHECKCOMMAND::$service.check_command$\t"
				"HOSTSTATE::$host.state$\t"
				"HOSTSTATETYPE::$host.state_type$\t"
				"SERVICESTATE::$service.state$\t"
				"SERVICESTATETYPE::$service.state_type$";
		
}

double ObjectImpl<PerfdataWriter>::GetDefaultRotationInterval() const
{
	 return 30; 
}

bool ObjectImpl<PerfdataWriter>::GetDefaultEnableHa() const
{
	 return false; 
}


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


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


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


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


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


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


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


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

void ObjectImpl<PerfdataWriter>::ValidateEnableHa(const Lazy<bool>& lvalue, const ValidationUtils& utils)
{
	SimpleValidateEnableHa(lvalue, utils);
}

void ObjectImpl<PerfdataWriter>::ValidateHostFormatTemplate(const Lazy<String>& lvalue, const ValidationUtils& utils)
{
	SimpleValidateHostFormatTemplate(lvalue, utils);
}

void ObjectImpl<PerfdataWriter>::ValidateHostPerfdataPath(const Lazy<String>& lvalue, const ValidationUtils& utils)
{
	SimpleValidateHostPerfdataPath(lvalue, utils);
}

void ObjectImpl<PerfdataWriter>::ValidateHostTempPath(const Lazy<String>& lvalue, const ValidationUtils& utils)
{
	SimpleValidateHostTempPath(lvalue, utils);
}

void ObjectImpl<PerfdataWriter>::ValidateRotationInterval(const Lazy<double>& lvalue, const ValidationUtils& utils)
{
	SimpleValidateRotationInterval(lvalue, utils);
}

void ObjectImpl<PerfdataWriter>::ValidateServiceFormatTemplate(const Lazy<String>& lvalue, const ValidationUtils& utils)
{
	SimpleValidateServiceFormatTemplate(lvalue, utils);
}

void ObjectImpl<PerfdataWriter>::ValidateServicePerfdataPath(const Lazy<String>& lvalue, const ValidationUtils& utils)
{
	SimpleValidateServicePerfdataPath(lvalue, utils);
}

void ObjectImpl<PerfdataWriter>::ValidateServiceTempPath(const Lazy<String>& lvalue, const ValidationUtils& utils)
{
	SimpleValidateServiceTempPath(lvalue, utils);
}

}
#pragma GCC diagnostic pop
