#ifndef COMMENT_TI
#define COMMENT_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 "base/configobject.hpp"

#include "base/utility.hpp"

namespace icinga
{


/**
 * The type of a service comment.
 *
 * @ingroup icinga
 */
enum CommentType
{
	CommentUser = 1,
	CommentAcknowledgement = 4
};

class CommentNameComposer : 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 Comment;

template<>
class TypeImpl<Comment> : public TypeImpl<ConfigObject>, public CommentNameComposer
{
public:
	DECLARE_PTR_TYPEDEFS(TypeImpl<Comment>);

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

	void Validate(int types, const ValidationUtils& utils) override;
	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 SimpleValidateText(const Lazy<String>& value, const ValidationUtils& utils);
	void SimpleValidateRemovedBy(const Lazy<String>& value, const ValidationUtils& utils);
	void SimpleValidateLegacyId(const Lazy<int>& value, const ValidationUtils& utils);
	void SimpleValidateEntryType(const Lazy<CommentType>& value, const ValidationUtils& utils);
	void SimpleValidateEntryTime(const Lazy<Timestamp>& value, const ValidationUtils& utils);
	void SimpleValidateExpireTime(const Lazy<Timestamp>& value, const ValidationUtils& utils);
	void SimpleValidateRemoveTime(const Lazy<Timestamp>& value, const ValidationUtils& utils);
	void SimpleValidateSticky(const Lazy<bool>& value, const ValidationUtils& utils);
	void SimpleValidatePersistent(const Lazy<bool>& value, const ValidationUtils& utils);
public:
	ObjectImpl<Comment>();
public:
	~ObjectImpl<Comment>() 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;
protected:
	String GetHostName() const;
protected:
	String GetServiceName() const;
public:
	String GetAuthor() const;
public:
	String GetText() const;
public:
	String GetRemovedBy() const;
public:
	int GetLegacyId() const;
public:
	CommentType GetEntryType() const;
public:
	Timestamp GetEntryTime() const;
public:
	Timestamp GetExpireTime() const;
public:
	Timestamp GetRemoveTime() const;
public:
	bool GetSticky() const;
public:
	bool GetPersistent() const;
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 SetText(const String& value, bool suppress_events = false, const Value& cookie = Empty);
public:
	void SetRemovedBy(const String& value, bool suppress_events = false, const Value& cookie = Empty);
public:
	void SetLegacyId(int value, bool suppress_events = false, const Value& cookie = Empty);
public:
	void SetEntryType(const CommentType& value, bool suppress_events = false, const Value& cookie = Empty);
public:
	void SetEntryTime(const Timestamp& value, bool suppress_events = false, const Value& cookie = Empty);
public:
	void SetExpireTime(const Timestamp& value, bool suppress_events = false, const Value& cookie = Empty);
public:
	void SetRemoveTime(const Timestamp& value, bool suppress_events = false, const Value& cookie = Empty);
public:
	void SetSticky(bool value, bool suppress_events = false, const Value& cookie = Empty);
public:
	void SetPersistent(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;
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 NotifyText(const Value& cookie = Empty);
public:
	virtual void NotifyRemovedBy(const Value& cookie = Empty);
public:
	virtual void NotifyLegacyId(const Value& cookie = Empty);
public:
	virtual void NotifyEntryType(const Value& cookie = Empty);
public:
	virtual void NotifyEntryTime(const Value& cookie = Empty);
public:
	virtual void NotifyExpireTime(const Value& cookie = Empty);
public:
	virtual void NotifyRemoveTime(const Value& cookie = Empty);
public:
	virtual void NotifySticky(const Value& cookie = Empty);
public:
	virtual void NotifyPersistent(const Value& cookie = Empty);
private:
	inline String GetDefaultHostName() const;
private:
	inline String GetDefaultServiceName() const;
private:
	inline String GetDefaultAuthor() const;
private:
	inline String GetDefaultText() const;
private:
	inline String GetDefaultRemovedBy() const;
private:
	inline int GetDefaultLegacyId() const;
private:
	inline CommentType GetDefaultEntryType() const;
private:
	inline Timestamp GetDefaultEntryTime() const;
private:
	inline Timestamp GetDefaultExpireTime() const;
private:
	inline Timestamp GetDefaultRemoveTime() const;
private:
	inline bool GetDefaultSticky() const;
private:
	inline bool GetDefaultPersistent() const;
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 ValidateText(const Lazy<String>& lvalue, const ValidationUtils& utils);
protected:
	virtual void ValidateRemovedBy(const Lazy<String>& lvalue, const ValidationUtils& utils);
protected:
	virtual void ValidateLegacyId(const Lazy<int>& lvalue, const ValidationUtils& utils);
protected:
	virtual void ValidateEntryType(const Lazy<CommentType>& lvalue, const ValidationUtils& utils);
protected:
	virtual void ValidateEntryTime(const Lazy<Timestamp>& lvalue, const ValidationUtils& utils);
protected:
	virtual void ValidateExpireTime(const Lazy<Timestamp>& lvalue, const ValidationUtils& utils);
protected:
	virtual void ValidateRemoveTime(const Lazy<Timestamp>& lvalue, const ValidationUtils& utils);
protected:
	virtual void ValidateSticky(const Lazy<bool>& lvalue, const ValidationUtils& utils);
protected:
	virtual void ValidatePersistent(const Lazy<bool>& lvalue, const ValidationUtils& utils);
private:
	AtomicOrLocked<String> m_HostName;
	AtomicOrLocked<String> m_ServiceName;
	AtomicOrLocked<String> m_Author;
	AtomicOrLocked<String> m_Text;
	AtomicOrLocked<String> m_RemovedBy;
	AtomicOrLocked<int> m_LegacyId;
	AtomicOrLocked<CommentType> m_EntryType;
	AtomicOrLocked<Timestamp> m_EntryTime;
	AtomicOrLocked<Timestamp> m_ExpireTime;
	AtomicOrLocked<Timestamp> m_RemoveTime;
	AtomicOrLocked<bool> m_Sticky;
	AtomicOrLocked<bool> m_Persistent;
public:
	static boost::signals2::signal<void (const intrusive_ptr<Comment>&, const Value&)> OnHostNameChanged;
	static boost::signals2::signal<void (const intrusive_ptr<Comment>&, const Value&)> OnServiceNameChanged;
	static boost::signals2::signal<void (const intrusive_ptr<Comment>&, const Value&)> OnAuthorChanged;
	static boost::signals2::signal<void (const intrusive_ptr<Comment>&, const Value&)> OnTextChanged;
	static boost::signals2::signal<void (const intrusive_ptr<Comment>&, const Value&)> OnRemovedByChanged;
	static boost::signals2::signal<void (const intrusive_ptr<Comment>&, const Value&)> OnLegacyIdChanged;
	static boost::signals2::signal<void (const intrusive_ptr<Comment>&, const Value&)> OnEntryTypeChanged;
	static boost::signals2::signal<void (const intrusive_ptr<Comment>&, const Value&)> OnEntryTimeChanged;
	static boost::signals2::signal<void (const intrusive_ptr<Comment>&, const Value&)> OnExpireTimeChanged;
	static boost::signals2::signal<void (const intrusive_ptr<Comment>&, const Value&)> OnRemoveTimeChanged;
	static boost::signals2::signal<void (const intrusive_ptr<Comment>&, const Value&)> OnStickyChanged;
	static boost::signals2::signal<void (const intrusive_ptr<Comment>&, const Value&)> OnPersistentChanged;
	friend class CommentNameComposer;
};

}
#endif /* COMMENT_TI */
