#ifndef PERFDATAVALUE_TI
#define PERFDATAVALUE_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>

namespace icinga
{

class PerfdataValue;

template<>
class TypeImpl<PerfdataValue> : public Type
{
public:
	DECLARE_PTR_TYPEDEFS(TypeImpl<PerfdataValue>);

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

	void Validate(int types, const ValidationUtils& utils) override;
	void SimpleValidateCrit(const Lazy<Value>& value, const ValidationUtils& utils);
	void SimpleValidateWarn(const Lazy<Value>& value, const ValidationUtils& utils);
	void SimpleValidateMin(const Lazy<Value>& value, const ValidationUtils& utils);
	void SimpleValidateMax(const Lazy<Value>& value, const ValidationUtils& utils);
	void SimpleValidateLabel(const Lazy<String>& value, const ValidationUtils& utils);
	void SimpleValidateUnit(const Lazy<String>& value, const ValidationUtils& utils);
	void SimpleValidateValue(const Lazy<double>& value, const ValidationUtils& utils);
	void SimpleValidateCounter(const Lazy<bool>& value, const ValidationUtils& utils);
public:
	ObjectImpl<PerfdataValue>();
public:
	~ObjectImpl<PerfdataValue>() 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 GetCrit() const;
public:
	Value GetWarn() const;
public:
	Value GetMin() const;
public:
	Value GetMax() const;
public:
	String GetLabel() const;
public:
	String GetUnit() const;
public:
	double GetValue() const;
public:
	bool GetCounter() const;
public:
	void SetCrit(const Value& value, bool suppress_events = false, const Value& cookie = Empty);
public:
	void SetWarn(const Value& value, bool suppress_events = false, const Value& cookie = Empty);
public:
	void SetMin(const Value& value, bool suppress_events = false, const Value& cookie = Empty);
public:
	void SetMax(const Value& value, bool suppress_events = false, const Value& cookie = Empty);
public:
	void SetLabel(const String& value, bool suppress_events = false, const Value& cookie = Empty);
public:
	void SetUnit(const String& value, bool suppress_events = false, const Value& cookie = Empty);
public:
	void SetValue(double value, bool suppress_events = false, const Value& cookie = Empty);
public:
	void SetCounter(bool value, bool suppress_events = false, const Value& cookie = Empty);
protected:
public:
	virtual void NotifyCrit(const Value& cookie = Empty);
public:
	virtual void NotifyWarn(const Value& cookie = Empty);
public:
	virtual void NotifyMin(const Value& cookie = Empty);
public:
	virtual void NotifyMax(const Value& cookie = Empty);
public:
	virtual void NotifyLabel(const Value& cookie = Empty);
public:
	virtual void NotifyUnit(const Value& cookie = Empty);
public:
	virtual void NotifyValue(const Value& cookie = Empty);
public:
	virtual void NotifyCounter(const Value& cookie = Empty);
private:
	inline Value GetDefaultCrit() const;
private:
	inline Value GetDefaultWarn() const;
private:
	inline Value GetDefaultMin() const;
private:
	inline Value GetDefaultMax() const;
private:
	inline String GetDefaultLabel() const;
private:
	inline String GetDefaultUnit() const;
private:
	inline double GetDefaultValue() const;
private:
	inline bool GetDefaultCounter() const;
protected:
	virtual void ValidateCrit(const Lazy<Value>& lvalue, const ValidationUtils& utils);
protected:
	virtual void ValidateWarn(const Lazy<Value>& lvalue, const ValidationUtils& utils);
protected:
	virtual void ValidateMin(const Lazy<Value>& lvalue, const ValidationUtils& utils);
protected:
	virtual void ValidateMax(const Lazy<Value>& lvalue, const ValidationUtils& utils);
protected:
	virtual void ValidateLabel(const Lazy<String>& lvalue, const ValidationUtils& utils);
protected:
	virtual void ValidateUnit(const Lazy<String>& lvalue, const ValidationUtils& utils);
protected:
	virtual void ValidateValue(const Lazy<double>& lvalue, const ValidationUtils& utils);
protected:
	virtual void ValidateCounter(const Lazy<bool>& lvalue, const ValidationUtils& utils);
private:
	AtomicOrLocked<Value> m_Crit;
	AtomicOrLocked<Value> m_Warn;
	AtomicOrLocked<Value> m_Min;
	AtomicOrLocked<Value> m_Max;
	AtomicOrLocked<String> m_Label;
	AtomicOrLocked<String> m_Unit;
	AtomicOrLocked<double> m_Value;
	AtomicOrLocked<bool> m_Counter;
public:
	static boost::signals2::signal<void (const intrusive_ptr<PerfdataValue>&, const Value&)> OnCritChanged;
	static boost::signals2::signal<void (const intrusive_ptr<PerfdataValue>&, const Value&)> OnWarnChanged;
	static boost::signals2::signal<void (const intrusive_ptr<PerfdataValue>&, const Value&)> OnMinChanged;
	static boost::signals2::signal<void (const intrusive_ptr<PerfdataValue>&, const Value&)> OnMaxChanged;
	static boost::signals2::signal<void (const intrusive_ptr<PerfdataValue>&, const Value&)> OnLabelChanged;
	static boost::signals2::signal<void (const intrusive_ptr<PerfdataValue>&, const Value&)> OnUnitChanged;
	static boost::signals2::signal<void (const intrusive_ptr<PerfdataValue>&, const Value&)> OnValueChanged;
	static boost::signals2::signal<void (const intrusive_ptr<PerfdataValue>&, const Value&)> OnCounterChanged;
};

}
#endif /* PERFDATAVALUE_TI */
