#ifndef DEPENDENCY_TI
#define DEPENDENCY_TI

#include "base/object.hpp"
#include "base/type.hpp"
#include "base/value.hpp"
#include "base/array.hpp"
#include "base/atomic.hpp"
#include "base/dictionary.hpp"
#include <boost/signals2.hpp>

#include "icinga/customvarobject.hpp"

#include "icinga/checkable.hpp"

namespace icinga
{


class DependencyNameComposer : public NameComposer
{
public:
	virtual String MakeName(const String& shortName, const Object::Ptr& context) const override;
	virtual Dictionary::Ptr ParseName(const String& name) const override;
};

class Dependency;

template<>
class TypeImpl<Dependency> : public TypeImpl<CustomVarObject>, public DependencyNameComposer
{
public:
	DECLARE_PTR_TYPEDEFS(TypeImpl<Dependency>);

	TypeImpl();
	~TypeImpl() override;

	String GetName() const override;
	int GetAttributes() const override;
	Type::Ptr GetBaseType() const override;
	int GetFieldId(const String& name) const override;
	Field GetFieldInfo(int id) const override;
	int GetFieldCount() const override;
	ObjectFactory GetFactory() const override;
	const std::unordered_set<Type*>& GetLoadDependencies() const override;
	int GetActivationPriority() const override;
public:
	void RegisterAttributeHandler(int fieldId, const Type::AttributeHandler& callback) override;
};


template<>
class ObjectImpl<Dependency> : public CustomVarObject
{
public:
	DECLARE_PTR_TYPEDEFS(ObjectImpl<Dependency>);

	void Validate(int types, const ValidationUtils& utils) override;
	void SimpleValidateChildHostName(const Lazy<String>& value, const ValidationUtils& utils);
	void SimpleValidateChildServiceName(const Lazy<String>& value, const ValidationUtils& utils);
	void SimpleValidateParentHostName(const Lazy<String>& value, const ValidationUtils& utils);
	void SimpleValidateParentServiceName(const Lazy<String>& value, const ValidationUtils& utils);
	void SimpleValidateRedundancyGroup(const Lazy<String>& value, const ValidationUtils& utils);
	void SimpleValidatePeriodRaw(const Lazy<String>& value, const ValidationUtils& utils);
	void SimpleValidateStates(const Lazy<Array::Ptr>& avalue, const ValidationUtils& utils);
	void SimpleValidateStateFilter(const Lazy<int>& value, const ValidationUtils& utils);
	void SimpleValidateIgnoreSoftStates(const Lazy<bool>& value, const ValidationUtils& utils);
	void SimpleValidateDisableChecks(const Lazy<bool>& value, const ValidationUtils& utils);
	void SimpleValidateDisableNotifications(const Lazy<bool>& value, const ValidationUtils& utils);
public:
	ObjectImpl<Dependency>();
public:
	~ObjectImpl<Dependency>() override;
public:
	void SetField(int id, const Value& value, bool suppress_events = false, const Value& cookie = Empty) override;
public:
	Value GetField(int id) const override;
public:
	void ValidateField(int id, const Lazy<Value>& lvalue, const ValidationUtils& utils) override;
public:
	void NotifyField(int id, const Value& cookie = Empty) override;
public:
	Object::Ptr NavigateField(int id) const override;
public:
	String GetChildHostName() const;
public:
	String GetChildServiceName() const;
public:
	String GetParentHostName() const;
public:
	String GetParentServiceName() const;
public:
	String GetRedundancyGroup() const;
public:
	String GetPeriodRaw() const;
public:
	Array::Ptr GetStates() const;
public:
	int GetStateFilter() const;
public:
	bool GetIgnoreSoftStates() const;
public:
	bool GetDisableChecks() const;
public:
	bool GetDisableNotifications() const;
public:
	void SetChildHostName(const String& value, bool suppress_events = false, const Value& cookie = Empty);
public:
	void SetChildServiceName(const String& value, bool suppress_events = false, const Value& cookie = Empty);
public:
	void SetParentHostName(const String& value, bool suppress_events = false, const Value& cookie = Empty);
public:
	void SetParentServiceName(const String& value, bool suppress_events = false, const Value& cookie = Empty);
public:
	void SetRedundancyGroup(const String& value, bool suppress_events = false, const Value& cookie = Empty);
public:
	void SetPeriodRaw(const String& value, bool suppress_events = false, const Value& cookie = Empty);
public:
	void SetStates(const Array::Ptr& value, bool suppress_events = false, const Value& cookie = Empty);
public:
	void SetStateFilter(int value, bool suppress_events = false, const Value& cookie = Empty);
public:
	void SetIgnoreSoftStates(bool value, bool suppress_events = false, const Value& cookie = Empty);
public:
	void SetDisableChecks(bool value, bool suppress_events = false, const Value& cookie = Empty);
public:
	void SetDisableNotifications(bool value, bool suppress_events = false, const Value& cookie = Empty);
protected:
	void TrackChildHostName(const String& oldValue, const String& newValue);
	void TrackChildServiceName(const String& oldValue, const String& newValue);
	void TrackParentHostName(const String& oldValue, const String& newValue);
	void TrackParentServiceName(const String& oldValue, const String& newValue);
	void TrackPeriodRaw(const String& oldValue, const String& newValue);
public:
	Object::Ptr NavigateChildHostName() const;
public:
	Object::Ptr NavigateChildServiceName() const;
public:
	Object::Ptr NavigateParentHostName() const;
public:
	Object::Ptr NavigateParentServiceName() const;
public:
	Object::Ptr NavigatePeriodRaw() const;
protected:
	void Start(bool runtimeCreated = false) override;
	void Stop(bool runtimeRemoved = false) override;
public:
	virtual void NotifyChildHostName(const Value& cookie = Empty);
public:
	virtual void NotifyChildServiceName(const Value& cookie = Empty);
public:
	virtual void NotifyParentHostName(const Value& cookie = Empty);
public:
	virtual void NotifyParentServiceName(const Value& cookie = Empty);
public:
	virtual void NotifyRedundancyGroup(const Value& cookie = Empty);
public:
	virtual void NotifyPeriodRaw(const Value& cookie = Empty);
public:
	virtual void NotifyStates(const Value& cookie = Empty);
public:
	virtual void NotifyStateFilter(const Value& cookie = Empty);
public:
	virtual void NotifyIgnoreSoftStates(const Value& cookie = Empty);
public:
	virtual void NotifyDisableChecks(const Value& cookie = Empty);
public:
	virtual void NotifyDisableNotifications(const Value& cookie = Empty);
private:
	inline String GetDefaultChildHostName() const;
private:
	inline String GetDefaultChildServiceName() const;
private:
	inline String GetDefaultParentHostName() const;
private:
	inline String GetDefaultParentServiceName() const;
private:
	inline String GetDefaultRedundancyGroup() const;
private:
	inline String GetDefaultPeriodRaw() const;
private:
	inline Array::Ptr GetDefaultStates() const;
private:
	inline int GetDefaultStateFilter() const;
private:
	inline bool GetDefaultIgnoreSoftStates() const;
private:
	inline bool GetDefaultDisableChecks() const;
private:
	inline bool GetDefaultDisableNotifications() const;
protected:
	virtual void ValidateChildHostName(const Lazy<String>& lvalue, const ValidationUtils& utils);
protected:
	virtual void ValidateChildServiceName(const Lazy<String>& lvalue, const ValidationUtils& utils);
protected:
	virtual void ValidateParentHostName(const Lazy<String>& lvalue, const ValidationUtils& utils);
protected:
	virtual void ValidateParentServiceName(const Lazy<String>& lvalue, const ValidationUtils& utils);
protected:
	virtual void ValidateRedundancyGroup(const Lazy<String>& lvalue, const ValidationUtils& utils);
protected:
	virtual void ValidatePeriodRaw(const Lazy<String>& lvalue, const ValidationUtils& utils);
protected:
	virtual void ValidateStates(const Lazy<Array::Ptr>& lvalue, const ValidationUtils& utils);
protected:
	virtual void ValidateStateFilter(const Lazy<int>& lvalue, const ValidationUtils& utils);
protected:
	virtual void ValidateIgnoreSoftStates(const Lazy<bool>& lvalue, const ValidationUtils& utils);
protected:
	virtual void ValidateDisableChecks(const Lazy<bool>& lvalue, const ValidationUtils& utils);
protected:
	virtual void ValidateDisableNotifications(const Lazy<bool>& lvalue, const ValidationUtils& utils);
private:
	AtomicOrLocked<String> m_ChildHostName;
	AtomicOrLocked<String> m_ChildServiceName;
	AtomicOrLocked<String> m_ParentHostName;
	AtomicOrLocked<String> m_ParentServiceName;
	AtomicOrLocked<String> m_RedundancyGroup;
	AtomicOrLocked<String> m_PeriodRaw;
	AtomicOrLocked<Array::Ptr> m_States;
	AtomicOrLocked<int> m_StateFilter;
	AtomicOrLocked<bool> m_IgnoreSoftStates;
	AtomicOrLocked<bool> m_DisableChecks;
	AtomicOrLocked<bool> m_DisableNotifications;
public:
	static boost::signals2::signal<void (const intrusive_ptr<Dependency>&, const Value&)> OnChildHostNameChanged;
	static boost::signals2::signal<void (const intrusive_ptr<Dependency>&, const Value&)> OnChildServiceNameChanged;
	static boost::signals2::signal<void (const intrusive_ptr<Dependency>&, const Value&)> OnParentHostNameChanged;
	static boost::signals2::signal<void (const intrusive_ptr<Dependency>&, const Value&)> OnParentServiceNameChanged;
	static boost::signals2::signal<void (const intrusive_ptr<Dependency>&, const Value&)> OnRedundancyGroupChanged;
	static boost::signals2::signal<void (const intrusive_ptr<Dependency>&, const Value&)> OnPeriodRawChanged;
	static boost::signals2::signal<void (const intrusive_ptr<Dependency>&, const Value&)> OnStatesChanged;
	static boost::signals2::signal<void (const intrusive_ptr<Dependency>&, const Value&)> OnStateFilterChanged;
	static boost::signals2::signal<void (const intrusive_ptr<Dependency>&, const Value&)> OnIgnoreSoftStatesChanged;
	static boost::signals2::signal<void (const intrusive_ptr<Dependency>&, const Value&)> OnDisableChecksChanged;
	static boost::signals2::signal<void (const intrusive_ptr<Dependency>&, const Value&)> OnDisableNotificationsChanged;
	friend class DependencyNameComposer;
};

}
#endif /* DEPENDENCY_TI */
