#pragma once
#include <vector>
#include "PropertiesInterface.h"
#include <crtdbg.h>

namespace NDTS
{
	namespace SCO
	{
	class Log;
	class GroupPropertyInternal;
	class PropertyInternal;
	
	class HardwareAccessClass
	{
	public:
		// Send this value to the hardware.  The value has been bounds checked already.  
		// The value should either be applied or not.  Any clamping should be done in the group hooks.
		// Return true if the value was written to hardware or false if the write failed.
		// This function must be overridden if it is going to be used in the hardware specific SDK.
		virtual bool setValue(int newValue){newValue; _ASSERTE(0); return false;}
		// Returns the value from hardware corresponding to this object.
		virtual int getValue(){_ASSERTE(0); return -1;}
		// A pointer to the propery that has been created with a link to this object.
		PropertyInternal *pAssociatedProperty;
	};

	enum HardwareAccessClassUsage
	{
		useFunctionPointers,
		writeToHardwareReadFromCachedValue,
		writeIsErrorReadFromHardware,
		writeToHardwareReadFromHardware, 
		writeToHardwareEvenIfNoChangeReadFromHardware,  // Do the register write even if the value is the same as that previously written 
		readFromCacheUpdateAfterHardwareInit  // Used for dummy values that never read or write to registers directly but do need to do an UpdateValue once after hardware init (e.g. number of cards)
	};

	class SCO_API PropertyInternal : public virtual Property
	{
	public:
		PropertyInternal(char *pShortName, char *pLongName, int flags);
		virtual ~PropertyInternal(void);
		virtual const char *getShortName();
		virtual const char *getLongName();
		virtual int getFlags();
		virtual void initComplete();  
		virtual void setBackPointer(void *pBackPointer);
		virtual void *getBackPointer();

		// Should not be called from application
		bool updateFlags(int newFlags);

		// Todo: Why can't these be protected?
		GroupPropertyInternal *pParent;
		void addShadow(Property *pProperty);

	protected:
		bool isInitComplete;
		Log *pLog;
		char *pShortName;
		char *pLongName;
		int flags;
#pragma warning(push)
#pragma warning(disable : 4251)			// Disable warning warning C4251: 'Sco::GroupPropertyInternal::propertyVector' : class 'std::vector<_Ty>' needs to have dll-interface to be used by clients of class 'NdtsSco::GroupPropertyInternal
		std::vector <Property *> shadowingProperties;
#pragma warning (pop)
		void createChangeItem(ChangeTypeFlags flags);
		void createChangeItemForShadowingProperties(ChangeTypeFlags flags);

	private:
		void *pBackPointer;
	};
}}
