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

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

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

int TypeImpl<DateTime>::GetAttributes() const
{
	return 2;
}

Type::Ptr TypeImpl<DateTime>::GetBaseType() const
{
	return Object::TypeInstance;
}

int TypeImpl<DateTime>::GetFieldId(const String& name) const
{
	int offset = 0;

	switch (static_cast<int>(Utility::SDBM(name, 1))) {
		case 118:
			if (name == "value")
				return offset + 0;

			break;
	}

	return -1;
}

Field TypeImpl<DateTime>::GetFieldInfo(int id) const
{
	switch (id) {
		case 0:
			return {0, "Timestamp", "value", "value", nullptr, 68, 0};
		default:
			throw std::runtime_error("Invalid field ID.");
	}
}

int TypeImpl<DateTime>::GetFieldCount() const
{
	return 1;
}

ObjectFactory TypeImpl<DateTime>::GetFactory() const
{
	return TypeHelper<DateTime, true>::GetFactory();
}

int TypeImpl<DateTime>::GetActivationPriority() const
{
	return 0;
}

void TypeImpl<DateTime>::RegisterAttributeHandler(int fieldId, const Type::AttributeHandler& callback)
{
	switch (fieldId) {
		case 0:
			ObjectImpl<DateTime>::OnValueChanged.connect(callback);
			break;
		default:
			throw std::runtime_error("Invalid field ID.");
	}
}

void ObjectImpl<DateTime>::Validate(int types, const ValidationUtils& utils)
{
	if (4 & types)
		ValidateValue(Lazy<Timestamp>([this]() { return GetValue(); }), utils);
}

void ObjectImpl<DateTime>::SimpleValidateValue(const Lazy<Timestamp>& value, const ValidationUtils& utils)
{
}

ObjectImpl<DateTime>::ObjectImpl()
{
	SetValue(GetDefaultValue(), true);
}

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

void ObjectImpl<DateTime>::SetField(int id, const Value& value, bool suppress_events, const Value& cookie)
{
	switch (id) {
		case 0:
			SetValue(value, suppress_events, cookie);
			break;
		default:
			throw std::runtime_error("Invalid field ID.");
	}
}

Value ObjectImpl<DateTime>::GetField(int id) const
{
	switch (id) {
		case 0:
			return GetValue();
		default:
			throw std::runtime_error("Invalid field ID.");
	}
}

void ObjectImpl<DateTime>::ValidateField(int id, const Lazy<Value>& lvalue, const ValidationUtils& utils)
{
	switch (id) {
		case 0:
			ValidateValue(lvalue, utils);
			break;
		default:
			throw std::runtime_error("Invalid field ID.");
	}
}

void ObjectImpl<DateTime>::NotifyField(int id, const Value& cookie)
{
	switch (id) {
		case 0:
			NotifyValue(cookie);
			break;
		default:
			throw std::runtime_error("Invalid field ID.");
	}
}

Object::Ptr ObjectImpl<DateTime>::NavigateField(int id) const
{
	throw std::runtime_error("Invalid field ID.");
}

void ObjectImpl<DateTime>::SetValue(const Timestamp& value, bool suppress_events, const Value& cookie)
{


	if (!suppress_events) {
		NotifyValue(cookie);
	}

}

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

Timestamp ObjectImpl<DateTime>::GetDefaultValue() const
{
	return Timestamp();
}


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

void ObjectImpl<DateTime>::ValidateValue(const Lazy<Timestamp>& lvalue, const ValidationUtils& utils)
{
	SimpleValidateValue(lvalue, utils);
}

}
#pragma GCC diagnostic pop
