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

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

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

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

Type::Ptr TypeImpl<TimePeriod>::GetBaseType() const
{
	return CustomVarObject::TypeInstance;
}

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

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

			break;
		case 101:
			if (name == "excludes")
				return offset + 3;

			break;
		case 105:
			if (name == "includes")
				return offset + 4;
			if (name == "is_inside")
				return offset + 9;

			break;
		case 112:
			if (name == "prefer_includes")
				return offset + 8;

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

			break;
		case 115:
			if (name == "segments")
				return offset + 5;

			break;
		case 117:
			if (name == "update")
				return offset + 7;

			break;
		case 118:
			if (name == "valid_begin")
				return offset + 0;
			if (name == "valid_end")
				return offset + 1;

			break;
	}

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

Field TypeImpl<TimePeriod>::GetFieldInfo(int id) const
{
	int real_id = id - CustomVarObject::TypeInstance->GetFieldCount();
	if (real_id < 0) { return CustomVarObject::TypeInstance->GetFieldInfo(id); }
	switch (real_id) {
		case 0:
			return {0, "Value", "valid_begin", "valid_begin", nullptr, 1028, 0};
		case 1:
			return {1, "Value", "valid_end", "valid_end", nullptr, 1028, 0};
		case 2:
			return {2, "String", "display_name", "display_name", nullptr, 2, 0};
		case 3:
			return {3, "Array", "excludes", "excludes", "TimePeriod", 65794, 1};
		case 4:
			return {4, "Array", "includes", "includes", "TimePeriod", 65794, 1};
		case 5:
			return {5, "Array", "segments", "segments", nullptr, 1028, 0};
		case 6:
			return {6, "Dictionary", "ranges", "ranges", nullptr, 65538, 0};
		case 7:
			return {7, "Function", "update", "update", nullptr, 258, 0};
		case 8:
			return {8, "Boolean", "prefer_includes", "prefer_includes", nullptr, 2, 0};
		case 9:
			return {9, "Boolean", "is_inside", "is_inside", nullptr, 65, 0};
		default:
			throw std::runtime_error("Invalid field ID.");
	}
}

int TypeImpl<TimePeriod>::GetFieldCount() const
{
	return 10 + CustomVarObject::TypeInstance->GetFieldCount();
}

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

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

void TypeImpl<TimePeriod>::RegisterAttributeHandler(int fieldId, const Type::AttributeHandler& callback)
{
	int real_id = fieldId - CustomVarObject::TypeInstance->GetFieldCount(); 
	if (real_id < 0) { CustomVarObject::TypeInstance->RegisterAttributeHandler(fieldId, callback); return; }
	switch (real_id) {
		case 0:
			ObjectImpl<TimePeriod>::OnValidBeginChanged.connect(callback);
			break;
		case 1:
			ObjectImpl<TimePeriod>::OnValidEndChanged.connect(callback);
			break;
		case 2:
			ObjectImpl<TimePeriod>::OnDisplayNameChanged.connect(callback);
			break;
		case 3:
			ObjectImpl<TimePeriod>::OnExcludesChanged.connect(callback);
			break;
		case 4:
			ObjectImpl<TimePeriod>::OnIncludesChanged.connect(callback);
			break;
		case 5:
			ObjectImpl<TimePeriod>::OnSegmentsChanged.connect(callback);
			break;
		case 6:
			ObjectImpl<TimePeriod>::OnRangesChanged.connect(callback);
			break;
		case 7:
			ObjectImpl<TimePeriod>::OnUpdateChanged.connect(callback);
			break;
		case 8:
			ObjectImpl<TimePeriod>::OnPreferIncludesChanged.connect(callback);
			break;
		case 9:
			ObjectImpl<TimePeriod>::OnIsInsideChanged.connect(callback);
			break;
		default:
			throw std::runtime_error("Invalid field ID.");
	}
}

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

	if (4 & types)
		ValidateValidBegin(Lazy<Value>([this]() { return GetValidBegin(); }), utils);
	if (4 & types)
		ValidateValidEnd(Lazy<Value>([this]() { return GetValidEnd(); }), utils);
	if (2 & types)
		ValidateDisplayName(Lazy<String>([this]() { return GetDisplayName(); }), utils);
	if (2 & types)
		ValidateExcludes(Lazy<Array::Ptr>([this]() { return GetExcludes(); }), utils);
	if (2 & types)
		ValidateIncludes(Lazy<Array::Ptr>([this]() { return GetIncludes(); }), utils);
	if (4 & types)
		ValidateSegments(Lazy<Array::Ptr>([this]() { return GetSegments(); }), utils);
	if (2 & types)
		ValidateRanges(Lazy<Dictionary::Ptr>([this]() { return GetRanges(); }), utils);
	if (2 & types)
		ValidateUpdate(Lazy<Function::Ptr>([this]() { return GetUpdate(); }), utils);
	if (2 & types)
		ValidatePreferIncludes(Lazy<bool>([this]() { return GetPreferIncludes(); }), utils);
	if (1 & types)
		ValidateIsInside(Lazy<bool>([this]() { return GetIsInside(); }), utils);
}

void ObjectImpl<TimePeriod>::SimpleValidateValidBegin(const Lazy<Value>& value, const ValidationUtils& utils)
{
	if (value().IsObjectType<Function>()) {
		Function::Ptr func = value();
		if (func->IsDeprecated())
			Log(LogWarning, "TimePeriod") << "Attribute 'valid_begin' for object '" << dynamic_cast<ConfigObject *>(this)->GetName() << "' of type '" << dynamic_cast<ConfigObject *>(this)->GetReflectionType()->GetName() << "' is set to a deprecated function: " << func->GetName();
	}

}

void ObjectImpl<TimePeriod>::SimpleValidateValidEnd(const Lazy<Value>& value, const ValidationUtils& utils)
{
	if (value().IsObjectType<Function>()) {
		Function::Ptr func = value();
		if (func->IsDeprecated())
			Log(LogWarning, "TimePeriod") << "Attribute 'valid_end' for object '" << dynamic_cast<ConfigObject *>(this)->GetName() << "' of type '" << dynamic_cast<ConfigObject *>(this)->GetReflectionType()->GetName() << "' is set to a deprecated function: " << func->GetName();
	}

}

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

void ObjectImpl<TimePeriod>::SimpleValidateExcludes(const Lazy<Array::Ptr>& avalue, const ValidationUtils& utils)
{
	if (!avalue())
		BOOST_THROW_EXCEPTION(ValidationError(dynamic_cast<ConfigObject *>(this), { "excludes" }, "Attribute must not be empty."));

	if (avalue()) {
		ObjectLock olock(avalue());
		for (const Value& value : avalue()) {
			if (!value.IsEmpty() && !value.IsString())
				BOOST_THROW_EXCEPTION(ValidationError(dynamic_cast<ConfigObject *>(this), { "excludes" }, "It is not allowed to specify '" + value + "' of type '" + value.GetTypeName() + "' as 'TimePeriod' name. Expected type of 'TimePeriod' name: 'String'."));
			if (value.IsEmpty() || !utils.ValidateName("TimePeriod", value))
				BOOST_THROW_EXCEPTION(ValidationError(dynamic_cast<ConfigObject *>(this), { "excludes" }, "Object '" + value + "' of type 'TimePeriod' does not exist."));
		}
	}
}

void ObjectImpl<TimePeriod>::SimpleValidateIncludes(const Lazy<Array::Ptr>& avalue, const ValidationUtils& utils)
{
	if (!avalue())
		BOOST_THROW_EXCEPTION(ValidationError(dynamic_cast<ConfigObject *>(this), { "includes" }, "Attribute must not be empty."));

	if (avalue()) {
		ObjectLock olock(avalue());
		for (const Value& value : avalue()) {
			if (!value.IsEmpty() && !value.IsString())
				BOOST_THROW_EXCEPTION(ValidationError(dynamic_cast<ConfigObject *>(this), { "includes" }, "It is not allowed to specify '" + value + "' of type '" + value.GetTypeName() + "' as 'TimePeriod' name. Expected type of 'TimePeriod' name: 'String'."));
			if (value.IsEmpty() || !utils.ValidateName("TimePeriod", value))
				BOOST_THROW_EXCEPTION(ValidationError(dynamic_cast<ConfigObject *>(this), { "includes" }, "Object '" + value + "' of type 'TimePeriod' does not exist."));
		}
	}
}

void ObjectImpl<TimePeriod>::SimpleValidateSegments(const Lazy<Array::Ptr>& value, const ValidationUtils& utils)
{
}

void ObjectImpl<TimePeriod>::SimpleValidateRanges(const Lazy<Dictionary::Ptr>& value, const ValidationUtils& utils)
{
}

void ObjectImpl<TimePeriod>::SimpleValidateUpdate(const Lazy<Function::Ptr>& value, const ValidationUtils& utils)
{
	if (!value())
		BOOST_THROW_EXCEPTION(ValidationError(dynamic_cast<ConfigObject *>(this), { "update" }, "Attribute must not be empty."));

}

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

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

ObjectImpl<TimePeriod>::ObjectImpl()
{
	SetValidBegin(GetDefaultValidBegin(), true);
	SetValidEnd(GetDefaultValidEnd(), true);
	SetDisplayName(GetDefaultDisplayName(), true);
	SetExcludes(GetDefaultExcludes(), true);
	SetIncludes(GetDefaultIncludes(), true);
	SetSegments(GetDefaultSegments(), true);
	SetRanges(GetDefaultRanges(), true);
	SetUpdate(GetDefaultUpdate(), true);
	SetPreferIncludes(GetDefaultPreferIncludes(), true);
	SetIsInside(GetDefaultIsInside(), true);
}

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

void ObjectImpl<TimePeriod>::SetField(int id, const Value& value, bool suppress_events, const Value& cookie)
{
	int real_id = id - CustomVarObject::TypeInstance->GetFieldCount(); 
	if (real_id < 0) { CustomVarObject::SetField(id, value, suppress_events, cookie); return; }
	switch (real_id) {
		case 0:
			SetValidBegin(value, suppress_events, cookie);
			break;
		case 1:
			SetValidEnd(value, suppress_events, cookie);
			break;
		case 2:
			SetDisplayName(value, suppress_events, cookie);
			break;
		case 3:
			SetExcludes(value, suppress_events, cookie);
			break;
		case 4:
			SetIncludes(value, suppress_events, cookie);
			break;
		case 5:
			SetSegments(value, suppress_events, cookie);
			break;
		case 6:
			SetRanges(value, suppress_events, cookie);
			break;
		case 7:
			SetUpdate(value, suppress_events, cookie);
			break;
		case 8:
			SetPreferIncludes(value, suppress_events, cookie);
			break;
		case 9:
			SetIsInside(value, suppress_events, cookie);
			break;
		default:
			throw std::runtime_error("Invalid field ID.");
	}
}

Value ObjectImpl<TimePeriod>::GetField(int id) const
{
	int real_id = id - CustomVarObject::TypeInstance->GetFieldCount(); 
	if (real_id < 0) { return CustomVarObject::GetField(id); }
	switch (real_id) {
		case 0:
			return GetValidBegin();
		case 1:
			return GetValidEnd();
		case 2:
			return GetDisplayName();
		case 3:
			return GetExcludes();
		case 4:
			return GetIncludes();
		case 5:
			return GetSegments();
		case 6:
			return GetRanges();
		case 7:
			return GetUpdate();
		case 8:
			return GetPreferIncludes();
		case 9:
			return GetIsInside();
		default:
			throw std::runtime_error("Invalid field ID.");
	}
}

void ObjectImpl<TimePeriod>::ValidateField(int id, const Lazy<Value>& lvalue, const ValidationUtils& utils)
{
	int real_id = id - CustomVarObject::TypeInstance->GetFieldCount(); 
	if (real_id < 0) { CustomVarObject::ValidateField(id, lvalue, utils); return; }
	switch (real_id) {
		case 0:
			ValidateValidBegin(lvalue, utils);
			break;
		case 1:
			ValidateValidEnd(lvalue, utils);
			break;
		case 2:
			ValidateDisplayName(lvalue, utils);
			break;
		case 3:
			ValidateExcludes(lvalue, utils);
			break;
		case 4:
			ValidateIncludes(lvalue, utils);
			break;
		case 5:
			ValidateSegments(lvalue, utils);
			break;
		case 6:
			ValidateRanges(lvalue, utils);
			break;
		case 7:
			ValidateUpdate(lvalue, utils);
			break;
		case 8:
			ValidatePreferIncludes(lvalue, utils);
			break;
		case 9:
			ValidateIsInside(lvalue, utils);
			break;
		default:
			throw std::runtime_error("Invalid field ID.");
	}
}

void ObjectImpl<TimePeriod>::NotifyField(int id, const Value& cookie)
{
	int real_id = id - CustomVarObject::TypeInstance->GetFieldCount(); 
	if (real_id < 0) { CustomVarObject::NotifyField(id, cookie); return; }
	switch (real_id) {
		case 0:
			NotifyValidBegin(cookie);
			break;
		case 1:
			NotifyValidEnd(cookie);
			break;
		case 2:
			NotifyDisplayName(cookie);
			break;
		case 3:
			NotifyExcludes(cookie);
			break;
		case 4:
			NotifyIncludes(cookie);
			break;
		case 5:
			NotifySegments(cookie);
			break;
		case 6:
			NotifyRanges(cookie);
			break;
		case 7:
			NotifyUpdate(cookie);
			break;
		case 8:
			NotifyPreferIncludes(cookie);
			break;
		case 9:
			NotifyIsInside(cookie);
			break;
		default:
			throw std::runtime_error("Invalid field ID.");
	}
}

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

Value ObjectImpl<TimePeriod>::GetValidBegin() const
{
	return m_ValidBegin.load();
}

Value ObjectImpl<TimePeriod>::GetValidEnd() const
{
	return m_ValidEnd.load();
}

String ObjectImpl<TimePeriod>::GetDisplayName() const
{

			String displayName = m_DisplayName.load();
			if (displayName.IsEmpty())
				return GetName();
			else
				return displayName;
		
}

Array::Ptr ObjectImpl<TimePeriod>::GetExcludes() const
{
	return m_Excludes.load();
}

Array::Ptr ObjectImpl<TimePeriod>::GetIncludes() const
{
	return m_Includes.load();
}

Array::Ptr ObjectImpl<TimePeriod>::GetSegments() const
{
	return m_Segments.load();
}

Dictionary::Ptr ObjectImpl<TimePeriod>::GetRanges() const
{
	return m_Ranges.load();
}

Function::Ptr ObjectImpl<TimePeriod>::GetUpdate() const
{
	return m_Update.load();
}

bool ObjectImpl<TimePeriod>::GetPreferIncludes() const
{
	return m_PreferIncludes.load();
}

void ObjectImpl<TimePeriod>::SetValidBegin(const Value& value, bool suppress_events, const Value& cookie)
{
	m_ValidBegin.store(value);
	if (!suppress_events) {
		NotifyValidBegin(cookie);
	}

}

void ObjectImpl<TimePeriod>::SetValidEnd(const Value& value, bool suppress_events, const Value& cookie)
{
	m_ValidEnd.store(value);
	if (!suppress_events) {
		NotifyValidEnd(cookie);
	}

}

void ObjectImpl<TimePeriod>::SetDisplayName(const String& value, bool suppress_events, const Value& cookie)
{
	m_DisplayName.store(value);
	if (!suppress_events) {
		NotifyDisplayName(cookie);
	}

}

void ObjectImpl<TimePeriod>::SetExcludes(const Array::Ptr& value, bool suppress_events, const Value& cookie)
{
	Value oldValue = GetExcludes();
	auto *dobj = dynamic_cast<ConfigObject *>(this);
	m_Excludes.store(value);
	if (!dobj || dobj->IsActive())
		TrackExcludes(oldValue, value);
	if (!suppress_events) {
		NotifyExcludes(cookie);
		if (!dobj || dobj->IsActive())
			OnExcludesChangedWithOldValue(static_cast<TimePeriod *>(this), oldValue, value);
	}

}

void ObjectImpl<TimePeriod>::SetIncludes(const Array::Ptr& value, bool suppress_events, const Value& cookie)
{
	Value oldValue = GetIncludes();
	auto *dobj = dynamic_cast<ConfigObject *>(this);
	m_Includes.store(value);
	if (!dobj || dobj->IsActive())
		TrackIncludes(oldValue, value);
	if (!suppress_events) {
		NotifyIncludes(cookie);
		if (!dobj || dobj->IsActive())
			OnIncludesChangedWithOldValue(static_cast<TimePeriod *>(this), oldValue, value);
	}

}

void ObjectImpl<TimePeriod>::SetSegments(const Array::Ptr& value, bool suppress_events, const Value& cookie)
{
	m_Segments.store(value);
	if (!suppress_events) {
		NotifySegments(cookie);
	}

}

void ObjectImpl<TimePeriod>::SetRanges(const Dictionary::Ptr& value, bool suppress_events, const Value& cookie)
{
	Value oldValue = GetRanges();
	auto *dobj = dynamic_cast<ConfigObject *>(this);
	m_Ranges.store(value);
	if (!suppress_events) {
		NotifyRanges(cookie);
		if (!dobj || dobj->IsActive())
			OnRangesChangedWithOldValue(static_cast<TimePeriod *>(this), oldValue, value);
	}

}

void ObjectImpl<TimePeriod>::SetUpdate(const Function::Ptr& value, bool suppress_events, const Value& cookie)
{
	m_Update.store(value);
	if (!suppress_events) {
		NotifyUpdate(cookie);
	}

}

void ObjectImpl<TimePeriod>::SetPreferIncludes(bool value, bool suppress_events, const Value& cookie)
{
	m_PreferIncludes.store(value);
	if (!suppress_events) {
		NotifyPreferIncludes(cookie);
	}

}

void ObjectImpl<TimePeriod>::SetIsInside(bool value, bool suppress_events, const Value& cookie)
{


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

}

void ObjectImpl<TimePeriod>::TrackExcludes(const Array::Ptr& oldValue, const Array::Ptr& newValue)
{
	if (oldValue) {
		ObjectLock olock(oldValue);
		for (auto& ref : oldValue) {
			DependencyGraph::RemoveDependency(this, ConfigObject::GetObject<TimePeriod>(ref).get());
		}
	}
	if (newValue) {
		ObjectLock olock(newValue);
		for (auto& ref : newValue) {
			DependencyGraph::AddDependency(this, ConfigObject::GetObject<TimePeriod>(ref).get());
		}
	}
}

void ObjectImpl<TimePeriod>::TrackIncludes(const Array::Ptr& oldValue, const Array::Ptr& newValue)
{
	if (oldValue) {
		ObjectLock olock(oldValue);
		for (auto& ref : oldValue) {
			DependencyGraph::RemoveDependency(this, ConfigObject::GetObject<TimePeriod>(ref).get());
		}
	}
	if (newValue) {
		ObjectLock olock(newValue);
		for (auto& ref : newValue) {
			DependencyGraph::AddDependency(this, ConfigObject::GetObject<TimePeriod>(ref).get());
		}
	}
}

void ObjectImpl<TimePeriod>::Start(bool runtimeCreated)
{
	CustomVarObject::Start(runtimeCreated);

	TrackExcludes(Empty, GetExcludes());
	TrackIncludes(Empty, GetIncludes());
}

void ObjectImpl<TimePeriod>::Stop(bool runtimeRemoved)
{
	CustomVarObject::Stop(runtimeRemoved);

	TrackExcludes(GetExcludes(), Empty);
	TrackIncludes(GetIncludes(), Empty);
}

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

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

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

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

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

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

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

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

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

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

Value ObjectImpl<TimePeriod>::GetDefaultValidBegin() const
{
	return Value();
}

Value ObjectImpl<TimePeriod>::GetDefaultValidEnd() const
{
	return Value();
}

String ObjectImpl<TimePeriod>::GetDefaultDisplayName() const
{
	return String();
}

Array::Ptr ObjectImpl<TimePeriod>::GetDefaultExcludes() const
{
	 return new Array(); 
}

Array::Ptr ObjectImpl<TimePeriod>::GetDefaultIncludes() const
{
	 return new Array(); 
}

Array::Ptr ObjectImpl<TimePeriod>::GetDefaultSegments() const
{
	return Array::Ptr();
}

Dictionary::Ptr ObjectImpl<TimePeriod>::GetDefaultRanges() const
{
	return Dictionary::Ptr();
}

Function::Ptr ObjectImpl<TimePeriod>::GetDefaultUpdate() const
{
	return Function::Ptr();
}

bool ObjectImpl<TimePeriod>::GetDefaultPreferIncludes() const
{
	 return true; 
}

bool ObjectImpl<TimePeriod>::GetDefaultIsInside() const
{
	return bool();
}


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


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


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


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


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


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


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


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


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


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


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


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


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

static void TIValidateTimePeriod_1(const intrusive_ptr<ObjectImpl<TimePeriod> >& object, const String& key, const Value& value, std::vector<String>& location, const ValidationUtils& utils)
{
	bool known_attribute = false;
	do {
		known_attribute = true;
		if (value.IsEmpty() || value.IsScalar())
			return;
	} while (0);

	if (!known_attribute)
		BOOST_THROW_EXCEPTION(ValidationError(dynamic_pointer_cast<ConfigObject>(object), location, "Invalid attribute: " + key));
	else
		BOOST_THROW_EXCEPTION(ValidationError(dynamic_pointer_cast<ConfigObject>(object), location, "Invalid type."));
}

static void TIValidateTimePeriodDisplayName(const intrusive_ptr<ObjectImpl<TimePeriod> >& object, const String& value, std::vector<String>& location, const ValidationUtils& utils)
{
	if (value.IsEmpty())
		return;

}

static void TIValidateTimePeriodExcludes(const intrusive_ptr<ObjectImpl<TimePeriod> >& object, const Array::Ptr& value, std::vector<String>& location, const ValidationUtils& utils)
{
	if (!value)
		return;

}

static void TIValidateTimePeriodIncludes(const intrusive_ptr<ObjectImpl<TimePeriod> >& object, const Array::Ptr& value, std::vector<String>& location, const ValidationUtils& utils)
{
	if (!value)
		return;

}

static void TIValidateTimePeriodIsInside(const intrusive_ptr<ObjectImpl<TimePeriod> >& object, bool value, std::vector<String>& location, const ValidationUtils& utils)
{
	if (!value)
		return;

}

static void TIValidateTimePeriodPreferIncludes(const intrusive_ptr<ObjectImpl<TimePeriod> >& object, bool value, std::vector<String>& location, const ValidationUtils& utils)
{
	if (!value)
		return;

}

static void TIValidateTimePeriodRanges(const intrusive_ptr<ObjectImpl<TimePeriod> >& object, const Dictionary::Ptr& value, std::vector<String>& location, const ValidationUtils& utils)
{
	if (!value)
		return;

	do {
		const Dictionary::Ptr& dict = value;
		{
			ObjectLock olock(dict);
			for (const Dictionary::Pair& kv : dict) {
				const String& akey = kv.first;
				const Value& avalue = kv.second;
				location.emplace_back(akey);
				TIValidateTimePeriod_1(object, akey, avalue, location, utils);
				location.pop_back();
			}
		}
		return;
	} while (0);

}

static void TIValidateTimePeriodSegments(const intrusive_ptr<ObjectImpl<TimePeriod> >& object, const Array::Ptr& value, std::vector<String>& location, const ValidationUtils& utils)
{
	if (!value)
		return;

}

static void TIValidateTimePeriodUpdate(const intrusive_ptr<ObjectImpl<TimePeriod> >& object, const Function::Ptr& value, std::vector<String>& location, const ValidationUtils& utils)
{
	if (!value)
		return;

}

static void TIValidateTimePeriodValidBegin(const intrusive_ptr<ObjectImpl<TimePeriod> >& object, const Value& value, std::vector<String>& location, const ValidationUtils& utils)
{
	if (value.IsEmpty())
		return;

}

static void TIValidateTimePeriodValidEnd(const intrusive_ptr<ObjectImpl<TimePeriod> >& object, const Value& value, std::vector<String>& location, const ValidationUtils& utils)
{
	if (value.IsEmpty())
		return;

}

void ObjectImpl<TimePeriod>::ValidateDisplayName(const Lazy<String>& lvalue, const ValidationUtils& utils)
{
	SimpleValidateDisplayName(lvalue, utils);
	std::vector<String> location;
	location.emplace_back("display_name");
	TIValidateTimePeriodDisplayName(this, lvalue(), location, utils);
	location.pop_back();
}

void ObjectImpl<TimePeriod>::ValidateExcludes(const Lazy<Array::Ptr>& lvalue, const ValidationUtils& utils)
{
	SimpleValidateExcludes(lvalue, utils);
	std::vector<String> location;
	location.emplace_back("excludes");
	TIValidateTimePeriodExcludes(this, lvalue(), location, utils);
	location.pop_back();
}

void ObjectImpl<TimePeriod>::ValidateIncludes(const Lazy<Array::Ptr>& lvalue, const ValidationUtils& utils)
{
	SimpleValidateIncludes(lvalue, utils);
	std::vector<String> location;
	location.emplace_back("includes");
	TIValidateTimePeriodIncludes(this, lvalue(), location, utils);
	location.pop_back();
}

void ObjectImpl<TimePeriod>::ValidateIsInside(const Lazy<bool>& lvalue, const ValidationUtils& utils)
{
	SimpleValidateIsInside(lvalue, utils);
	std::vector<String> location;
	location.emplace_back("is_inside");
	TIValidateTimePeriodIsInside(this, lvalue(), location, utils);
	location.pop_back();
}

void ObjectImpl<TimePeriod>::ValidatePreferIncludes(const Lazy<bool>& lvalue, const ValidationUtils& utils)
{
	SimpleValidatePreferIncludes(lvalue, utils);
	std::vector<String> location;
	location.emplace_back("prefer_includes");
	TIValidateTimePeriodPreferIncludes(this, lvalue(), location, utils);
	location.pop_back();
}

void ObjectImpl<TimePeriod>::ValidateRanges(const Lazy<Dictionary::Ptr>& lvalue, const ValidationUtils& utils)
{
	SimpleValidateRanges(lvalue, utils);
	std::vector<String> location;
	location.emplace_back("ranges");
	TIValidateTimePeriodRanges(this, lvalue(), location, utils);
	location.pop_back();
}

void ObjectImpl<TimePeriod>::ValidateSegments(const Lazy<Array::Ptr>& lvalue, const ValidationUtils& utils)
{
	SimpleValidateSegments(lvalue, utils);
	std::vector<String> location;
	location.emplace_back("segments");
	TIValidateTimePeriodSegments(this, lvalue(), location, utils);
	location.pop_back();
}

void ObjectImpl<TimePeriod>::ValidateUpdate(const Lazy<Function::Ptr>& lvalue, const ValidationUtils& utils)
{
	SimpleValidateUpdate(lvalue, utils);
	std::vector<String> location;
	location.emplace_back("update");
	TIValidateTimePeriodUpdate(this, lvalue(), location, utils);
	location.pop_back();
}

void ObjectImpl<TimePeriod>::ValidateValidBegin(const Lazy<Value>& lvalue, const ValidationUtils& utils)
{
	SimpleValidateValidBegin(lvalue, utils);
	std::vector<String> location;
	location.emplace_back("valid_begin");
	TIValidateTimePeriodValidBegin(this, lvalue(), location, utils);
	location.pop_back();
}

void ObjectImpl<TimePeriod>::ValidateValidEnd(const Lazy<Value>& lvalue, const ValidationUtils& utils)
{
	SimpleValidateValidEnd(lvalue, utils);
	std::vector<String> location;
	location.emplace_back("valid_end");
	TIValidateTimePeriodValidEnd(this, lvalue(), location, utils);
	location.pop_back();
}

}
#pragma GCC diagnostic pop
