#ifndef ENDPOINT_TI
#define ENDPOINT_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 <cstdint>

namespace icinga
{

class Endpoint;

template<>
class TypeImpl<Endpoint> : public TypeImpl<ConfigObject>
{
public:
	DECLARE_PTR_TYPEDEFS(TypeImpl<Endpoint>);

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

	void Validate(int types, const ValidationUtils& utils) override;
	void SimpleValidatePort(const Lazy<String>& value, const ValidationUtils& utils);
	void SimpleValidateHost(const Lazy<String>& value, const ValidationUtils& utils);
	void SimpleValidateMessagesSentPerSecond(const Lazy<double>& value, const ValidationUtils& utils);
	void SimpleValidateMessagesReceivedPerSecond(const Lazy<double>& value, const ValidationUtils& utils);
	void SimpleValidateBytesSentPerSecond(const Lazy<double>& value, const ValidationUtils& utils);
	void SimpleValidateBytesReceivedPerSecond(const Lazy<double>& value, const ValidationUtils& utils);
	void SimpleValidateLogDuration(const Lazy<double>& value, const ValidationUtils& utils);
	void SimpleValidateSecondsProcessingMessages(const Lazy<double>& value, const ValidationUtils& utils);
	void SimpleValidateMessagesReceivedPerType(const Lazy<Dictionary::Ptr>& value, const ValidationUtils& utils);
	void SimpleValidateLocalLogPosition(const Lazy<Timestamp>& value, const ValidationUtils& utils);
	void SimpleValidateRemoteLogPosition(const Lazy<Timestamp>& value, const ValidationUtils& utils);
	void SimpleValidateLastMessageReceived(const Lazy<Timestamp>& value, const ValidationUtils& utils);
	void SimpleValidateLastMessageSent(const Lazy<Timestamp>& value, const ValidationUtils& utils);
	void SimpleValidateConnected(const Lazy<bool>& value, const ValidationUtils& utils);
	void SimpleValidateSyncing(const Lazy<bool>& value, const ValidationUtils& utils);
	void SimpleValidateConnecting(const Lazy<bool>& value, const ValidationUtils& utils);
	void SimpleValidateCapabilities(const Lazy<uint_fast64_t>& value, const ValidationUtils& utils);
	void SimpleValidateIcingaVersion(const Lazy<unsigned long>& value, const ValidationUtils& utils);
public:
	ObjectImpl<Endpoint>();
public:
	~ObjectImpl<Endpoint>() 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 GetPort() const;
public:
	String GetHost() const;
public:
	virtual double GetMessagesSentPerSecond() const = 0;
public:
	virtual double GetMessagesReceivedPerSecond() const = 0;
public:
	virtual double GetBytesSentPerSecond() const = 0;
public:
	virtual double GetBytesReceivedPerSecond() const = 0;
public:
	double GetLogDuration() const;
public:
	virtual double GetSecondsProcessingMessages() const = 0;
public:
	virtual Dictionary::Ptr GetMessagesReceivedPerType() const = 0;
public:
	Timestamp GetLocalLogPosition() const;
public:
	Timestamp GetRemoteLogPosition() const;
public:
	Timestamp GetLastMessageReceived() const;
public:
	Timestamp GetLastMessageSent() const;
public:
	virtual bool GetConnected() const = 0;
public:
	bool GetSyncing() const;
public:
	bool GetConnecting() const;
public:
	uint_fast64_t GetCapabilities() const;
public:
	unsigned long GetIcingaVersion() const;
public:
	void SetPort(const String& value, bool suppress_events = false, const Value& cookie = Empty);
public:
	void SetHost(const String& value, bool suppress_events = false, const Value& cookie = Empty);
public:
	void SetMessagesSentPerSecond(double value, bool suppress_events = false, const Value& cookie = Empty);
public:
	void SetMessagesReceivedPerSecond(double value, bool suppress_events = false, const Value& cookie = Empty);
public:
	void SetBytesSentPerSecond(double value, bool suppress_events = false, const Value& cookie = Empty);
public:
	void SetBytesReceivedPerSecond(double value, bool suppress_events = false, const Value& cookie = Empty);
public:
	void SetLogDuration(double value, bool suppress_events = false, const Value& cookie = Empty);
public:
	void SetSecondsProcessingMessages(double value, bool suppress_events = false, const Value& cookie = Empty);
public:
	void SetMessagesReceivedPerType(const Dictionary::Ptr& value, bool suppress_events = false, const Value& cookie = Empty);
public:
	void SetLocalLogPosition(const Timestamp& value, bool suppress_events = false, const Value& cookie = Empty);
public:
	void SetRemoteLogPosition(const Timestamp& value, bool suppress_events = false, const Value& cookie = Empty);
public:
	void SetLastMessageReceived(const Timestamp& value, bool suppress_events = false, const Value& cookie = Empty);
public:
	void SetLastMessageSent(const Timestamp& value, bool suppress_events = false, const Value& cookie = Empty);
public:
	void SetConnected(bool value, bool suppress_events = false, const Value& cookie = Empty);
public:
	void SetSyncing(bool value, bool suppress_events = false, const Value& cookie = Empty);
public:
	void SetConnecting(bool value, bool suppress_events = false, const Value& cookie = Empty);
public:
	void SetCapabilities(const uint_fast64_t& value, bool suppress_events = false, const Value& cookie = Empty);
public:
	void SetIcingaVersion(const unsigned long& value, bool suppress_events = false, const Value& cookie = Empty);
protected:
public:
	virtual void NotifyPort(const Value& cookie = Empty);
public:
	virtual void NotifyHost(const Value& cookie = Empty);
public:
	virtual void NotifyMessagesSentPerSecond(const Value& cookie = Empty);
public:
	virtual void NotifyMessagesReceivedPerSecond(const Value& cookie = Empty);
public:
	virtual void NotifyBytesSentPerSecond(const Value& cookie = Empty);
public:
	virtual void NotifyBytesReceivedPerSecond(const Value& cookie = Empty);
public:
	virtual void NotifyLogDuration(const Value& cookie = Empty);
public:
	virtual void NotifySecondsProcessingMessages(const Value& cookie = Empty);
public:
	virtual void NotifyMessagesReceivedPerType(const Value& cookie = Empty);
public:
	virtual void NotifyLocalLogPosition(const Value& cookie = Empty);
public:
	virtual void NotifyRemoteLogPosition(const Value& cookie = Empty);
public:
	virtual void NotifyLastMessageReceived(const Value& cookie = Empty);
public:
	virtual void NotifyLastMessageSent(const Value& cookie = Empty);
public:
	virtual void NotifyConnected(const Value& cookie = Empty);
public:
	virtual void NotifySyncing(const Value& cookie = Empty);
public:
	virtual void NotifyConnecting(const Value& cookie = Empty);
public:
	virtual void NotifyCapabilities(const Value& cookie = Empty);
public:
	virtual void NotifyIcingaVersion(const Value& cookie = Empty);
private:
	inline String GetDefaultPort() const;
private:
	inline String GetDefaultHost() const;
private:
	inline double GetDefaultMessagesSentPerSecond() const;
private:
	inline double GetDefaultMessagesReceivedPerSecond() const;
private:
	inline double GetDefaultBytesSentPerSecond() const;
private:
	inline double GetDefaultBytesReceivedPerSecond() const;
private:
	inline double GetDefaultLogDuration() const;
private:
	inline double GetDefaultSecondsProcessingMessages() const;
private:
	inline Dictionary::Ptr GetDefaultMessagesReceivedPerType() const;
private:
	inline Timestamp GetDefaultLocalLogPosition() const;
private:
	inline Timestamp GetDefaultRemoteLogPosition() const;
private:
	inline Timestamp GetDefaultLastMessageReceived() const;
private:
	inline Timestamp GetDefaultLastMessageSent() const;
private:
	inline bool GetDefaultConnected() const;
private:
	inline bool GetDefaultSyncing() const;
private:
	inline bool GetDefaultConnecting() const;
private:
	inline uint_fast64_t GetDefaultCapabilities() const;
private:
	inline unsigned long GetDefaultIcingaVersion() const;
protected:
	virtual void ValidatePort(const Lazy<String>& lvalue, const ValidationUtils& utils);
protected:
	virtual void ValidateHost(const Lazy<String>& lvalue, const ValidationUtils& utils);
protected:
	virtual void ValidateMessagesSentPerSecond(const Lazy<double>& lvalue, const ValidationUtils& utils);
protected:
	virtual void ValidateMessagesReceivedPerSecond(const Lazy<double>& lvalue, const ValidationUtils& utils);
protected:
	virtual void ValidateBytesSentPerSecond(const Lazy<double>& lvalue, const ValidationUtils& utils);
protected:
	virtual void ValidateBytesReceivedPerSecond(const Lazy<double>& lvalue, const ValidationUtils& utils);
protected:
	virtual void ValidateLogDuration(const Lazy<double>& lvalue, const ValidationUtils& utils);
protected:
	virtual void ValidateSecondsProcessingMessages(const Lazy<double>& lvalue, const ValidationUtils& utils);
protected:
	virtual void ValidateMessagesReceivedPerType(const Lazy<Dictionary::Ptr>& lvalue, const ValidationUtils& utils);
protected:
	virtual void ValidateLocalLogPosition(const Lazy<Timestamp>& lvalue, const ValidationUtils& utils);
protected:
	virtual void ValidateRemoteLogPosition(const Lazy<Timestamp>& lvalue, const ValidationUtils& utils);
protected:
	virtual void ValidateLastMessageReceived(const Lazy<Timestamp>& lvalue, const ValidationUtils& utils);
protected:
	virtual void ValidateLastMessageSent(const Lazy<Timestamp>& lvalue, const ValidationUtils& utils);
protected:
	virtual void ValidateConnected(const Lazy<bool>& lvalue, const ValidationUtils& utils);
protected:
	virtual void ValidateSyncing(const Lazy<bool>& lvalue, const ValidationUtils& utils);
protected:
	virtual void ValidateConnecting(const Lazy<bool>& lvalue, const ValidationUtils& utils);
protected:
	virtual void ValidateCapabilities(const Lazy<uint_fast64_t>& lvalue, const ValidationUtils& utils);
protected:
	virtual void ValidateIcingaVersion(const Lazy<unsigned long>& lvalue, const ValidationUtils& utils);
private:
	AtomicOrLocked<String> m_Port;
	AtomicOrLocked<String> m_Host;
	AtomicOrLocked<double> m_LogDuration;
	AtomicOrLocked<Timestamp> m_LocalLogPosition;
	AtomicOrLocked<Timestamp> m_RemoteLogPosition;
	AtomicOrLocked<Timestamp> m_LastMessageReceived;
	AtomicOrLocked<Timestamp> m_LastMessageSent;
	AtomicOrLocked<bool> m_Syncing;
	AtomicOrLocked<bool> m_Connecting;
	AtomicOrLocked<uint_fast64_t> m_Capabilities;
	AtomicOrLocked<unsigned long> m_IcingaVersion;
public:
	static boost::signals2::signal<void (const intrusive_ptr<Endpoint>&, const Value&)> OnPortChanged;
	static boost::signals2::signal<void (const intrusive_ptr<Endpoint>&, const Value&)> OnHostChanged;
	static boost::signals2::signal<void (const intrusive_ptr<Endpoint>&, const Value&)> OnMessagesSentPerSecondChanged;
	static boost::signals2::signal<void (const intrusive_ptr<Endpoint>&, const Value&)> OnMessagesReceivedPerSecondChanged;
	static boost::signals2::signal<void (const intrusive_ptr<Endpoint>&, const Value&)> OnBytesSentPerSecondChanged;
	static boost::signals2::signal<void (const intrusive_ptr<Endpoint>&, const Value&)> OnBytesReceivedPerSecondChanged;
	static boost::signals2::signal<void (const intrusive_ptr<Endpoint>&, const Value&)> OnLogDurationChanged;
	static boost::signals2::signal<void (const intrusive_ptr<Endpoint>&, const Value&)> OnSecondsProcessingMessagesChanged;
	static boost::signals2::signal<void (const intrusive_ptr<Endpoint>&, const Value&)> OnMessagesReceivedPerTypeChanged;
	static boost::signals2::signal<void (const intrusive_ptr<Endpoint>&, const Value&)> OnLocalLogPositionChanged;
	static boost::signals2::signal<void (const intrusive_ptr<Endpoint>&, const Value&)> OnRemoteLogPositionChanged;
	static boost::signals2::signal<void (const intrusive_ptr<Endpoint>&, const Value&)> OnLastMessageReceivedChanged;
	static boost::signals2::signal<void (const intrusive_ptr<Endpoint>&, const Value&)> OnLastMessageSentChanged;
	static boost::signals2::signal<void (const intrusive_ptr<Endpoint>&, const Value&)> OnConnectedChanged;
	static boost::signals2::signal<void (const intrusive_ptr<Endpoint>&, const Value&)> OnSyncingChanged;
	static boost::signals2::signal<void (const intrusive_ptr<Endpoint>&, const Value&)> OnConnectingChanged;
	static boost::signals2::signal<void (const intrusive_ptr<Endpoint>&, const Value&)> OnCapabilitiesChanged;
	static boost::signals2::signal<void (const intrusive_ptr<Endpoint>&, const Value&)> OnIcingaVersionChanged;
};

}
#endif /* ENDPOINT_TI */
