#pragma once
#include "SignalSlot.h"
#include "Common.h"
BEGIN_NAMESPACE


template <class T>
class PropertyInterface : public InterfaceBase
{
public:
	virtual T const & get() const = 0;
	virtual void set(T a_newValue) = 0;
	
  // implementing cast and assignment operators is not the more C++ way?
  //virtual T const & operator()(void) const
	//virtual operator=(T const &) const
};


// This class is an abstract base class for a property
// The main thing to note is that it doesn't contain the
// variable backing this property which allows the value
// to come from any source or be held say inside of the
// library code or an engine, this API then exposes that
// through this interface. The only issue is that it
// requires that the library or engine code must call
// setValue when the value has changed to notify interested
// parties. The T type of this property however can be large
// or arbitary. The set re-implementation can also be made
// to be ref-count aware or implement something like a swap
// as is done in certain cases for assignment operators.

template <class T>
class AbstractProperty : public PropertyInterface<T>
{
public:
	AbstractProperty<T>& operator=(T const & a_newValue)
	{
		//Variant v = a_newValue;
		//setValue(v);
		setValue(a_newValue);
		return *this;
	}

	T const & operator()(void) const
	{
		return value();
	}

	void setValue(const T& a_newValue)
	{
		set(a_newValue);
		valueChanged(a_newValue);
	}
  /*
	void setValue(Variant& a_newValue)
	{
		set(a_newValue.variant_cast<T>());
		valueChanged(a_newValue);
	}
  */

	T const & value() const
	{
		return get();
	}

	//Signal valueChanged;
	Action<T> valueChanged;

protected:
	virtual T const & get() const = 0;
	virtual void set(T a_newValue) = 0;
};


// This is an implementation of the AbstractProperty interface
// which actually holds and backs the property with a variable
// of the given type.
// This is good for simple types where the declaration of the
// property also is intended to create the variable associated
// with it.
// In the case of a widget which manipulates a value, consider
// the widget instead passing and storing a AbstractProperty
// to it instead of a concrete value in a Property.
template <class T>
class Property : public AbstractProperty<T>
{
public:
	Property() {}
	Property(const T& val) : m_value(val) {}
	Property(const Property<T>& other) : m_value(other.m_value) {}
  
	Property<T>& operator=(T const & a_newValue)
	{
		//Variant v = a_newValue;
		//AbstractProperty<T>::setValue(v);
		AbstractProperty<T>::setValue(a_newValue);
		return *this;
	}

protected:
	T const & get() const { return m_value; }
	void set(T a_newValue) { m_value = a_newValue; }

private:
	T m_value;
};


END_NAMESPACE

