#ifndef DBCONNECTION_TI
#define DBCONNECTION_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 "db_ido/dbquery.hpp"

#include "base/configobject.hpp"

namespace icinga
{

class DbConnection;

template<>
struct TypeHelper<DbConnection, false>
{
	static ObjectFactory GetFactory()
	{
		return nullptr;
	}
};

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

	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;
	int GetActivationPriority() const override;
public:
	void RegisterAttributeHandler(int fieldId, const Type::AttributeHandler& callback) override;
};


template<>
class ObjectImpl<DbConnection> : public ConfigObject
{
public:
	DECLARE_PTR_TYPEDEFS(ObjectImpl<DbConnection>);

	void Validate(int types, const ValidationUtils& utils) override;
	void SimpleValidateTablePrefix(const Lazy<String>& value, const ValidationUtils& utils);
	void SimpleValidateSchemaVersion(const Lazy<String>& value, const ValidationUtils& utils);
	void SimpleValidateFailoverTimeout(const Lazy<double>& value, const ValidationUtils& utils);
	void SimpleValidateLastFailover(const Lazy<double>& value, const ValidationUtils& utils);
	void SimpleValidateCategories(const Lazy<Array::Ptr>& value, const ValidationUtils& utils);
	void SimpleValidateCleanup(const Lazy<Dictionary::Ptr>& value, const ValidationUtils& utils);
	void SimpleValidateCategoryFilter(const Lazy<int>& value, const ValidationUtils& utils);
	void SimpleValidateEnableHa(const Lazy<bool>& value, const ValidationUtils& utils);
	void SimpleValidateConnected(const Lazy<bool>& value, const ValidationUtils& utils);
	void SimpleValidateShouldConnect(const Lazy<bool>& value, const ValidationUtils& utils);
public:
	ObjectImpl<DbConnection>();
public:
	~ObjectImpl<DbConnection>() 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 GetTablePrefix() const;
public:
	String GetSchemaVersion() const;
public:
	double GetFailoverTimeout() const;
public:
	double GetLastFailover() const;
public:
	Array::Ptr GetCategories() const;
public:
	Dictionary::Ptr GetCleanup() const;
public:
	int GetCategoryFilter() const;
public:
	bool GetEnableHa() const;
public:
	bool GetConnected() const;
public:
	bool GetShouldConnect() const;
public:
	void SetTablePrefix(const String& value, bool suppress_events = false, const Value& cookie = Empty);
public:
	void SetSchemaVersion(const String& value, bool suppress_events = false, const Value& cookie = Empty);
public:
	void SetFailoverTimeout(double value, bool suppress_events = false, const Value& cookie = Empty);
public:
	void SetLastFailover(double value, bool suppress_events = false, const Value& cookie = Empty);
public:
	void SetCategories(const Array::Ptr& value, bool suppress_events = false, const Value& cookie = Empty);
public:
	void SetCleanup(const Dictionary::Ptr& value, bool suppress_events = false, const Value& cookie = Empty);
public:
	void SetCategoryFilter(int value, bool suppress_events = false, const Value& cookie = Empty);
public:
	void SetEnableHa(bool value, bool suppress_events = false, const Value& cookie = Empty);
public:
	void SetConnected(bool value, bool suppress_events = false, const Value& cookie = Empty);
public:
	void SetShouldConnect(bool value, bool suppress_events = false, const Value& cookie = Empty);
protected:
public:
	virtual void NotifyTablePrefix(const Value& cookie = Empty);
public:
	virtual void NotifySchemaVersion(const Value& cookie = Empty);
public:
	virtual void NotifyFailoverTimeout(const Value& cookie = Empty);
public:
	virtual void NotifyLastFailover(const Value& cookie = Empty);
public:
	virtual void NotifyCategories(const Value& cookie = Empty);
public:
	virtual void NotifyCleanup(const Value& cookie = Empty);
public:
	virtual void NotifyCategoryFilter(const Value& cookie = Empty);
public:
	virtual void NotifyEnableHa(const Value& cookie = Empty);
public:
	virtual void NotifyConnected(const Value& cookie = Empty);
public:
	virtual void NotifyShouldConnect(const Value& cookie = Empty);
private:
	inline String GetDefaultTablePrefix() const;
private:
	inline String GetDefaultSchemaVersion() const;
private:
	inline double GetDefaultFailoverTimeout() const;
private:
	inline double GetDefaultLastFailover() const;
private:
	inline Array::Ptr GetDefaultCategories() const;
private:
	inline Dictionary::Ptr GetDefaultCleanup() const;
private:
	inline int GetDefaultCategoryFilter() const;
private:
	inline bool GetDefaultEnableHa() const;
private:
	inline bool GetDefaultConnected() const;
private:
	inline bool GetDefaultShouldConnect() const;
protected:
	virtual void ValidateTablePrefix(const Lazy<String>& lvalue, const ValidationUtils& utils);
protected:
	virtual void ValidateSchemaVersion(const Lazy<String>& lvalue, const ValidationUtils& utils);
protected:
	virtual void ValidateFailoverTimeout(const Lazy<double>& lvalue, const ValidationUtils& utils);
protected:
	virtual void ValidateLastFailover(const Lazy<double>& lvalue, const ValidationUtils& utils);
protected:
	virtual void ValidateCategories(const Lazy<Array::Ptr>& lvalue, const ValidationUtils& utils);
protected:
	virtual void ValidateCleanup(const Lazy<Dictionary::Ptr>& lvalue, const ValidationUtils& utils);
protected:
	virtual void ValidateCategoryFilter(const Lazy<int>& lvalue, const ValidationUtils& utils);
protected:
	virtual void ValidateEnableHa(const Lazy<bool>& lvalue, const ValidationUtils& utils);
protected:
	virtual void ValidateConnected(const Lazy<bool>& lvalue, const ValidationUtils& utils);
protected:
	virtual void ValidateShouldConnect(const Lazy<bool>& lvalue, const ValidationUtils& utils);
private:
	AtomicOrLocked<String> m_TablePrefix;
	AtomicOrLocked<String> m_SchemaVersion;
	AtomicOrLocked<double> m_FailoverTimeout;
	AtomicOrLocked<double> m_LastFailover;
	AtomicOrLocked<Array::Ptr> m_Categories;
	AtomicOrLocked<Dictionary::Ptr> m_Cleanup;
	AtomicOrLocked<int> m_CategoryFilter;
	AtomicOrLocked<bool> m_EnableHa;
	AtomicOrLocked<bool> m_Connected;
	AtomicOrLocked<bool> m_ShouldConnect;
public:
	static boost::signals2::signal<void (const intrusive_ptr<DbConnection>&, const Value&)> OnTablePrefixChanged;
	static boost::signals2::signal<void (const intrusive_ptr<DbConnection>&, const Value&)> OnSchemaVersionChanged;
	static boost::signals2::signal<void (const intrusive_ptr<DbConnection>&, const Value&)> OnFailoverTimeoutChanged;
	static boost::signals2::signal<void (const intrusive_ptr<DbConnection>&, const Value&)> OnLastFailoverChanged;
	static boost::signals2::signal<void (const intrusive_ptr<DbConnection>&, const Value&)> OnCategoriesChanged;
	static boost::signals2::signal<void (const intrusive_ptr<DbConnection>&, const Value&)> OnCleanupChanged;
	static boost::signals2::signal<void (const intrusive_ptr<DbConnection>&, const Value&)> OnCategoryFilterChanged;
	static boost::signals2::signal<void (const intrusive_ptr<DbConnection>&, const Value&)> OnEnableHaChanged;
	static boost::signals2::signal<void (const intrusive_ptr<DbConnection>&, const Value&)> OnConnectedChanged;
	static boost::signals2::signal<void (const intrusive_ptr<DbConnection>&, const Value&)> OnShouldConnectChanged;
};

}
#endif /* DBCONNECTION_TI */
