//
//	Copyright © 2007 Nemetschek North America 
//	All Rights Reserved.
//
// Created by Vladislav Stanev

#pragma once

namespace VWFC
{
	using namespace VWObjects;
	using namespace Math;

	namespace Tools
	{
		// ----------------------------------------------------------------------------------------------------------------------------------
		class CParamProviderAbstract
		{
		public:
									CParamProviderAbstract();
			virtual					~CParamProviderAbstract();

		public:
			virtual long			GetParamLong(size_t paramIndex) const = 0;
			virtual void			SetParamLong(size_t paramIndex, long value) = 0;
			virtual bool			GetParamBool(size_t paramIndex) const = 0;
			virtual void			SetParamBool(size_t paramIndex, bool value) = 0;
			virtual double			GetParamReal(size_t paramIndex) const = 0;
			virtual void			SetParamReal(size_t paramIndex, double value) = 0;
			virtual TXString		GetParamString(size_t paramIndex) const = 0;
			virtual void			SetParamString(size_t paramIndex, const TXString& value) = 0;
			virtual VWPoint2D		GetParamCtrlPt(size_t paramIndexXCoord, size_t paramIndexYCoord) const = 0;
			virtual void			SetParamCtrlPt(size_t paramIndexXCoord, size_t paramIndexYCoord, const VWPoint2D& value) = 0;

			virtual bool			GetParamChoices(size_t paramIndex, TXStringSTLArray& outArray) const = 0;

		public:
			void					ProcessParameter(bool bRead, bool& inOutValue, bool oldVaue, size_t paramIndex);
			void					ProcessParameter(bool bRead, UInt32& inOutValue, UInt32 oldVaue, size_t paramIndex);
			void					ProcessParameter(bool bRead, SInt32& inOutValue, UInt32 oldVaue, size_t paramIndex);
			void					ProcessParameter(bool bRead, double& inOutValue, double oldVaue, size_t paramIndex);
			void					ProcessParameter(bool bRead, TXString& inOutValue, const TXString& oldVaue, size_t paramIndex);
			void					ProcessParameter(bool bRead, VWPoint2D& inOutValue, const VWPoint2D& oldVaue, size_t paramIndexXCoord, size_t paramIndexYCoord);
			template<class T>
				void				ProcessParameter(bool bRead, T& inOutValue, T oldVaue, size_t paramIndex, T defIndex);
			template<class T>
				void				ProcessParameter(bool bRead, T& inOutValue, T oldVaue, size_t paramIndex, T defIndex, char** arrStrings);

			UInt32					DecodeEnumString(size_t paramIndex, const TXString& string, UInt32 def) const;
			TXString				EncodeEnumString(size_t paramIndex, UInt32 index, UInt32 def) const;
			UInt32					DecodeEnumString(char** arrStrings, const TXString& string, UInt32 def) const;
			TXString				EncodeEnumString(char** arrStrings, UInt32 index, UInt32 defIndex) const;

		protected:
			bool					ResourceGetParamChoices(size_t paramIndex, TXStringSTLArray& outArray) const;
		};

		// --------------------------------------------------------------------------------------------------------
		class CObjectParamProvider : public CParamProviderAbstract
		{
		public:
										CObjectParamProvider(VWParametricObj& obj);
			virtual						~CObjectParamProvider();

		public:
			virtual long				GetParamLong(size_t paramIndex) const;
			virtual void				SetParamLong(size_t paramIndex, long value);
			virtual bool				GetParamBool(size_t paramIndex) const;
			virtual void				SetParamBool(size_t paramIndex, bool value);
			virtual double				GetParamReal(size_t paramIndex) const;
			virtual void				SetParamReal(size_t paramIndex, double value);
			virtual TXString			GetParamString(size_t paramIndex) const;
			virtual void				SetParamString(size_t paramIndex, const TXString& value);
			virtual VWPoint2D			GetParamCtrlPt(size_t paramIndexXCoord, size_t paramIndexYCoord) const;
			virtual void				SetParamCtrlPt(size_t paramIndexXCoord, size_t paramIndexYCoord, const VWPoint2D& value);

			virtual bool				GetParamChoices(size_t paramIndex, TXStringSTLArray& outArray) const;

		private:
			VWParametricObj				fObj;
		};

		// --------------------------------------------------------------------------------------------------------
		class CFormatParamProvider : public CParamProviderAbstract
		{
		public:
										CFormatParamProvider(VWRecordFormatObj& obj);
			virtual						~CFormatParamProvider();

		public:
			virtual long				GetParamLong(size_t paramIndex) const;
			virtual void				SetParamLong(size_t paramIndex, long value);
			virtual bool				GetParamBool(size_t paramIndex) const;
			virtual void				SetParamBool(size_t paramIndex, bool value);
			virtual double				GetParamReal(size_t paramIndex) const;
			virtual void				SetParamReal(size_t paramIndex, double value);
			virtual TXString			GetParamString(size_t paramIndex) const;
			virtual void				SetParamString(size_t paramIndex, const TXString& value);
			virtual VWPoint2D			GetParamCtrlPt(size_t paramIndexXCoord, size_t paramIndexYCoord) const;
			virtual void				SetParamCtrlPt(size_t paramIndexXCoord, size_t paramIndexYCoord, const VWPoint2D& value);

			virtual bool				GetParamChoices(size_t paramIndex, TXStringSTLArray& outArray) const;

		private:
			VWRecordFormatObj			fObj;
		};

		// ==================================================================================================
		// template impelementation

		// ---------------------------------------------------------------------------------------------------
		// Process enumeration parameter from parameter enumeration values
		// ---------------------------------------------------------------------------------------------------
		template <class T>
		void CParamProviderAbstract::ProcessParameter(bool bRead, T& inOutValue, T oldVaue, size_t paramIndex, T defIndex)
		{
			if ( bRead ) {
				TXString	strEncodedValue	= this->GetParamString( paramIndex );
				inOutValue					= (T) this->DecodeEnumString( paramIndex, strEncodedValue, defIndex );
			}
			else if ( oldVaue != inOutValue ) {
				TXString	strEncodedValue	= this->EncodeEnumString( paramIndex, inOutValue, defIndex );
				this->SetParamString( paramIndex, strEncodedValue );
			}
		}

		// ---------------------------------------------------------------------------------------------------
		// Process enumeration parameter from specified array
		// ---------------------------------------------------------------------------------------------------
		template<class T>
		void CParamProviderAbstract::ProcessParameter(bool bRead, T& inOutValue, T oldVaue, size_t paramIndex, T defIndex, char** arrStrings)
		{
			if ( bRead ) {
				TXString	strEncodedValue	= this->GetParamString( paramIndex );
				inOutValue					= (T) this->DecodeEnumString( arrStrings, strEncodedValue, defIndex );
			}
			else if ( oldVaue != inOutValue ) {
				TXString	strEncodedValue	= this->EncodeEnumString( arrStrings, inOutValue, defIndex );
				this->SetParamString( paramIndex, strEncodedValue );
			}
		}

	}
}