#ifndef SCHEDULEDDOWNTIME_TI
#define SCHEDULEDDOWNTIME_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"

namespace icinga
{


class ScheduledDowntimeNameComposer : 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 ScheduledDowntime;

template<>
class TypeImpl<ScheduledDowntime> : public TypeImpl<CustomVarObject>, public ScheduledDowntimeNameComposer
{
public:
	DECLARE_PTR_TYPEDEFS(TypeImpl<ScheduledDowntime>);

	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<ScheduledDowntime> : public CustomVarObject
{
public:
	DECLARE_PTR_TYPEDEFS(ObjectImpl<ScheduledDowntime>);

	void Validate(int types, const ValidationUtils& utils) override;
	void SimpleValidateChildOptions(const Lazy<Value>& value, const ValidationUtils& utils);
	void SimpleValidateHostName(const Lazy<String>& value, const ValidationUtils& utils);
	void SimpleValidateServiceName(const Lazy<String>& value, const ValidationUtils& utils);
	void SimpleValidateAuthor(const Lazy<String>& value, const ValidationUtils& utils);
	void SimpleValidateComment(const Lazy<String>& value, const ValidationUtils& utils);
	void SimpleValidateDuration(const Lazy<double>& value, const ValidationUtils& utils);
	void SimpleValidateRanges(const Lazy<Dictionary::Ptr>& value, const ValidationUtils& utils);
	void SimpleValidateFixed(const Lazy<bool>& value, const ValidationUtils& utils);
public:
	ObjectImpl<ScheduledDowntime>();
public:
	~ObjectImpl<ScheduledDowntime>() 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:
	Value GetChildOptions() const;
protected:
	String GetHostName() const;
protected:
	String GetServiceName() const;
public:
	String GetAuthor() const;
public:
	String GetComment() const;
public:
	double GetDuration() const;
public:
	Dictionary::Ptr GetRanges() const;
public:
	bool GetFixed() const;
public:
	void SetChildOptions(const Value& value, bool suppress_events = false, const Value& cookie = Empty);
protected:
	void SetHostName(const String& value, bool suppress_events = false, const Value& cookie = Empty);
protected:
	void SetServiceName(const String& value, bool suppress_events = false, const Value& cookie = Empty);
public:
	void SetAuthor(const String& value, bool suppress_events = false, const Value& cookie = Empty);
public:
	void SetComment(const String& value, bool suppress_events = false, const Value& cookie = Empty);
public:
	void SetDuration(double value, bool suppress_events = false, const Value& cookie = Empty);
public:
	void SetRanges(const Dictionary::Ptr& value, bool suppress_events = false, const Value& cookie = Empty);
public:
	void SetFixed(bool value, bool suppress_events = false, const Value& cookie = Empty);
protected:
	void TrackHostName(const String& oldValue, const String& newValue);
	void TrackServiceName(const String& oldValue, const String& newValue);
public:
	Object::Ptr NavigateHostName() const;
public:
	Object::Ptr NavigateServiceName() const;
protected:
	void Start(bool runtimeCreated = false) override;
	void Stop(bool runtimeRemoved = false) override;
public:
	virtual void NotifyChildOptions(const Value& cookie = Empty);
protected:
	virtual void NotifyHostName(const Value& cookie = Empty);
protected:
	virtual void NotifyServiceName(const Value& cookie = Empty);
public:
	virtual void NotifyAuthor(const Value& cookie = Empty);
public:
	virtual void NotifyComment(const Value& cookie = Empty);
public:
	virtual void NotifyDuration(const Value& cookie = Empty);
public:
	virtual void NotifyRanges(const Value& cookie = Empty);
public:
	virtual void NotifyFixed(const Value& cookie = Empty);
private:
	inline Value GetDefaultChildOptions() const;
private:
	inline String GetDefaultHostName() const;
private:
	inline String GetDefaultServiceName() const;
private:
	inline String GetDefaultAuthor() const;
private:
	inline String GetDefaultComment() const;
private:
	inline double GetDefaultDuration() const;
private:
	inline Dictionary::Ptr GetDefaultRanges() const;
private:
	inline bool GetDefaultFixed() const;
protected:
	virtual void ValidateChildOptions(const Lazy<Value>& lvalue, const ValidationUtils& utils);
protected:
	virtual void ValidateHostName(const Lazy<String>& lvalue, const ValidationUtils& utils);
protected:
	virtual void ValidateServiceName(const Lazy<String>& lvalue, const ValidationUtils& utils);
protected:
	virtual void ValidateAuthor(const Lazy<String>& lvalue, const ValidationUtils& utils);
protected:
	virtual void ValidateComment(const Lazy<String>& lvalue, const ValidationUtils& utils);
protected:
	virtual void ValidateDuration(const Lazy<double>& lvalue, const ValidationUtils& utils);
protected:
	virtual void ValidateRanges(const Lazy<Dictionary::Ptr>& lvalue, const ValidationUtils& utils);
protected:
	virtual void ValidateFixed(const Lazy<bool>& lvalue, const ValidationUtils& utils);
private:
	AtomicOrLocked<Value> m_ChildOptions;
	AtomicOrLocked<String> m_HostName;
	AtomicOrLocked<String> m_ServiceName;
	AtomicOrLocked<String> m_Author;
	AtomicOrLocked<String> m_Comment;
	AtomicOrLocked<double> m_Duration;
	AtomicOrLocked<Dictionary::Ptr> m_Ranges;
	AtomicOrLocked<bool> m_Fixed;
public:
	static boost::signals2::signal<void (const intrusive_ptr<ScheduledDowntime>&, const Value&)> OnChildOptionsChanged;
	static boost::signals2::signal<void (const intrusive_ptr<ScheduledDowntime>&, const Value&)> OnHostNameChanged;
	static boost::signals2::signal<void (const intrusive_ptr<ScheduledDowntime>&, const Value&)> OnServiceNameChanged;
	static boost::signals2::signal<void (const intrusive_ptr<ScheduledDowntime>&, const Value&)> OnAuthorChanged;
	static boost::signals2::signal<void (const intrusive_ptr<ScheduledDowntime>&, const Value&)> OnCommentChanged;
	static boost::signals2::signal<void (const intrusive_ptr<ScheduledDowntime>&, const Value&)> OnDurationChanged;
	static boost::signals2::signal<void (const intrusive_ptr<ScheduledDowntime>&, const Value&)> OnRangesChanged;
	static boost::signals2::signal<void (const intrusive_ptr<ScheduledDowntime>&, const Value&)> OnFixedChanged;
	friend class ScheduledDowntimeNameComposer;
};

}
#endif /* SCHEDULEDDOWNTIME_TI */
