/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2016 Raytrix GmbH. All rights reserved.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once

#include "DLLInterface.h"
#include "Pimpl.h"

#include "Rx.Core/RxString.h"
#include "Rx.Core.Ex/RxArrayUInt.h"
#include "Rx.Core.Ex/RxArrayDouble.h"
#include "Rx.Core.Ex/RxArrayString.h"
#include "Rx.Core.Ex/EValueType.h"
#include "Rx.Core.Ex/RxMetaData.h"

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// namespace: Rx.LFR
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
namespace Rx
{
	namespace LFR
	{
		template<class TEnum>
		class CParameters_Impl;

		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>
		/// 	A base of all classes that need to get or set parameters.
		/// </summary>
		///
		/// <typeparam name="TPimpl"> PIMPL. </typeparam>
		/// <typeparam name="TEnum">  The enum type that describes the parameter ID. </typeparam>
		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		template<class TEnum>
		class RX_API CParameters : public CPimpl<CParameters_Impl<TEnum>, Interfaces::EParameters::ID>
		{
		public:

			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			/// <summary>
			/// 	Constructor. Only for internal purposes.
			/// </summary>
			///
			/// <param name="pxImpl">		 [out] The implementation class. </param>
			/// <param name="bFreeOnDelete"> (Optional) True to free the memory of the given implementation class on deleting this object. </param>
			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			CParameters(CParameters_Impl<TEnum>* pxImpl, bool bFreeOnDelete = true);

			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			/// <summary>
			/// 	Protected destructor.
			/// </summary>
			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			~CParameters()
			{
			}

		public:

			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			/// <summary>
			/// 	Queries if the given value is a valid value for the given parameter ID. This tests the data type and possible
			/// 	constraints.
			/// </summary>
			///
			/// <param name="eID">    The parameter ID. </param>
			/// <param name="uValue"> The value. </param>
			///
			/// <returns> True if the value is valid, false if not. </returns>
			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			bool IsValueValid(TEnum eID, unsigned uValue) const;

			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			/// <summary>
			/// 	Queries if the given value is a valid value for the given parameter ID. This tests the data type and possible
			/// 	constraints.
			/// </summary>
			///
			/// <param name="eID">    The parameter ID. </param>
			/// <param name="dValue"> The value. </param>
			///
			/// <returns> True if the value is valid, false if not. </returns>
			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			bool IsValueValid(TEnum eID, double dValue) const;

			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			/// <summary>
			/// 	Queries if the given value is a valid value for the given parameter ID. This tests the data type and possible
			/// 	constraints.
			/// </summary>
			///
			/// <param name="eID">	   The parameter ID. </param>
			/// <param name="sxValue"> The value. </param>
			///
			/// <returns> True if the value is valid, false if not. </returns>
			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			bool IsValueValid(TEnum eID, const CRxString& sxValue) const;

			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			/// <summary>
			/// 	Queries if the given value is a valid value for the given parameter ID. This tests the data type and possible
			/// 	constraints.
			/// </summary>
			///
			/// <param name="eID">	   The parameter ID. </param>
			/// <param name="auValue"> The value. </param>
			///
			/// <returns> True if the value is valid, false if not. </returns>
			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			bool IsValueValid(TEnum eID, const CRxArrayUInt& auValue) const;

			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			/// <summary>
			/// 	Queries if the given value is a valid value for the given parameter ID. This tests the data type and possible
			/// 	constraints.
			/// </summary>
			///
			/// <param name="eID">	   The parameter ID. </param>
			/// <param name="adValue"> The value. </param>
			///
			/// <returns> True if the value is valid, false if not. </returns>
			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			bool IsValueValid(TEnum eID, const CRxArrayDouble& adValue) const;

			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			/// <summary>
			/// 	Queries if the given value is a valid value for the given parameter ID. This tests the data type and possible
			/// 	constraints.
			/// </summary>
			///
			/// <param name="eID">	   The parameter ID. </param>
			/// <param name="asValue"> The value. </param>
			///
			/// <returns> True if the value is valid, false if not. </returns>
			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			bool IsValueValid(TEnum eID, const CRxArrayString& asValue) const;

		public:

			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			/// <summary>
			/// 	Gets the valid range of the value that can be set to the given non-array parameter.
			/// </summary>
			///
			/// <param name="eID">  The parameter ID. </param>
			/// <param name="uMin"> [out] The minimum value. </param>
			/// <param name="uMax"> [out] The maximum value. </param>
			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			void GetValueRange(TEnum eID, unsigned& uMin, unsigned& uMax) const;

			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			/// <summary>
			/// 	Gets the valid range of the value that can be set to the given non-array parameter.
			/// </summary>
			///
			/// <param name="eID">  The parameter ID. </param>
			/// <param name="dMin"> [out] The minimum value. </param>
			/// <param name="dMax"> [out] The maximum value. </param>
			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			void GetValueRange(TEnum eID, double& dMin, double& dMax) const;

			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			/// <summary>
			/// 	Gets the valid range of the value that can be set to the given array parameter.
			/// </summary>
			///
			/// <param name="eID">		    The parameter ID. </param>
			/// <param name="nArrayLenMin"> [out] The minimum array length. </param>
			/// <param name="nArrayLenMax"> [out] The maximum array length. </param>
			/// <param name="uMin">		    [out] The minimum value of each array element. </param>
			/// <param name="uMax">		    [out] The maximum value of each array element. </param>
			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			void GetValueRange(TEnum eID, size_t& nArrayLenMin, size_t& nArrayLenMax, unsigned& uMin, unsigned& uMax) const;

			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			/// <summary>
			/// 	Gets the valid range of the value that can be set to the given array parameter.
			/// </summary>
			///
			/// <param name="eID">		    The parameter ID. </param>
			/// <param name="nArrayLenMin"> [out] The minimum array length. </param>
			/// <param name="nArrayLenMax"> [out] The maximum array length. </param>
			/// <param name="dMin">		    [out] The minimum value of each array element. </param>
			/// <param name="dMax">		    [out] The maximum value of each array element. </param>
			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			void GetValueRange(TEnum eID, size_t& nArrayLenMin, size_t& nArrayLenMax, double& dMin, double& dMax) const;

		public:

			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			/// <summary>
			/// 	Gets some parts of the parameter definition.
			/// </summary>
			///
			/// <param name="eID">    The parameter ID. </param>
			/// <param name="sxName"> [out] The parameter name. </param>
			/// <param name="sxGUID"> [out] The GUID of the parameter. </param>
			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			void GetDefinition(TEnum eID, CRxString& sxName, CRxString& sxGUID) const;

			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			/// <summary>
			/// 	Gets some parts of the parameter definition.
			/// </summary>
			///
			/// <param name="eID">		 The parameter ID. </param>
			/// <param name="sxName">    [out] The parameter name. </param>
			/// <param name="sxGUID">    [out] The GUID of the parameter. </param>
			/// <param name="bReadable"> [out] True if the parameter is readable. </param>
			/// <param name="bWritable"> [out] True if the parameter is writable. </param>
			/// <param name="eType">	 [out] The data type of the parameter. </param>
			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			void GetDefinition(TEnum eID, CRxString& sxName, CRxString& sxGUID, bool& bReadable, bool& bWritable, EValueType::ID& eType) const;

		public:

			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			/// <summary>
			/// 	Sets the parameter described by the given parameter ID to its initial or its default value.
			/// </summary>
			///
			/// <param name="eID">			   The parameter ID. </param>
			/// <param name="bResetToInitial"> (Optional) True to reset to initial, false to reset to default. </param>
			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			void Reset(TEnum eID, bool bResetToInitial = false);

			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			/// <summary>
			/// 	Sets all parameters to their initial or their default value.
			/// </summary>
			///
			/// <param name="bResetToInitial"> (Optional) True to reset to initial, false to reset to default. </param>
			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			void Reset(bool bResetToInitial = false);

		public:

			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			/// <summary>
			/// 	Sets the value of the given parameter.
			/// </summary>
			///
			/// <param name="eID">    The parameter ID. </param>
			/// <param name="uValue"> The value. </param>
			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			void SetValue(TEnum eID, unsigned uValue);

			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			/// <summary>
			/// 	Sets the value of the given parameter.
			/// </summary>
			///
			/// <param name="eID">    The parameter ID. </param>
			/// <param name="dValue"> The value. </param>
			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			void SetValue(TEnum eID, double dValue);

			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			/// <summary>
			/// 	Sets the value of the given parameter.
			/// </summary>
			///
			/// <param name="eID">	   The parameter ID. </param>
			/// <param name="sxValue"> The value. </param>
			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			void SetValue(TEnum eID, const CRxString& sxValue);

			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			/// <summary>
			/// 	Sets the value of the given parameter.
			/// </summary>
			///
			/// <param name="eID">	   The parameter ID. </param>
			/// <param name="auValue"> The value. </param>
			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			void SetValue(TEnum eID, const CRxArrayUInt& auValue);

			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			/// <summary>
			/// 	Sets the value of the given parameter.
			/// </summary>
			///
			/// <param name="eID">	   The parameter ID. </param>
			/// <param name="adValue"> The value. </param>
			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			void SetValue(TEnum eID, const CRxArrayDouble& adValue);

			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			/// <summary>
			/// 	Sets the value of the given parameter.
			/// </summary>
			///
			/// <param name="eID">	   The parameter ID. </param>
			/// <param name="asValue"> The value. </param>
			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			void SetValue(TEnum eID, const CRxArrayString& asValue);

		public:

			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			/// <summary>
			/// 	Gets the value of the given parameter.
			/// </summary>
			///
			/// <param name="eID">    The parameter ID. </param>
			/// <param name="uValue"> [out] The value. </param>
			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			void GetValue(TEnum eID, unsigned& uValue) const;

			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			/// <summary>
			/// 	Gets the value of the given parameter.
			/// </summary>
			///
			/// <param name="eID">    The parameter ID. </param>
			/// <param name="dValue"> [out] The value. </param>
			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			void GetValue(TEnum eID, double& dValue) const;

			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			/// <summary>
			/// 	Gets the value of the given parameter.
			/// </summary>
			///
			/// <param name="eID">	   The parameter ID. </param>
			/// <param name="sxValue"> [out] The value. </param>
			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			void GetValue(TEnum eID, CRxString& sxValue) const;

			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			/// <summary>
			/// 	Gets the value of the given parameter.
			/// </summary>
			///
			/// <param name="eID">	   The parameter ID. </param>
			/// <param name="auValue"> [out] The value. </param>
			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			void GetValue(TEnum eID, CRxArrayUInt& auValue) const;

			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			/// <summary>
			/// 	Gets the value of the given parameter.
			/// </summary>
			///
			/// <param name="eID">	   The parameter ID. </param>
			/// <param name="adValue"> [out] The value. </param>
			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			void GetValue(TEnum eID, CRxArrayDouble& adValue) const;

			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			/// <summary>
			/// 	Gets the value of the given parameter.
			/// </summary>
			///
			/// <param name="eID">	   The parameter ID. </param>
			/// <param name="asValue"> [out] The value. </param>
			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			void GetValue(TEnum eID, CRxArrayString& asValue) const;

		public:

			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			/// <summary>
			/// 	Gets the name of the given group ID.
			/// </summary>
			///
			/// <param name="eGroup"> The group ID. </param>
			///
			/// <returns> Empty string if the name is missing, else the group name. </returns>
			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			static const char* GetParamterGroupName(Params::EGroup::ID eGroup);

		public:

			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			/// <summary>
			/// 	Imports the parameter stored in the given file and applies each by calling SetValue.
			/// </summary>
			///
			/// <param name="sxFilename"> The file name. </param>
			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			void ImportParameterFromFile(const CRxString& sxFilename);

			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			/// <summary>
			/// 	Imports the parameter stored in the given XML string and applies each by calling SetValue.
			/// </summary>
			///
			/// <param name="sxXmlString"> The XML string. </param>
			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			void ImportParameterFromString(const CRxString& sxXmlString);

			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			/// <summary>
			/// 	Import from meta data.
			/// </summary>
			///
			/// <param name="xMetaData"> the meta data. </param>
			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			void ImportFromMetaData(const CRxMetaData& xMetaData);

		public:

			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			/// <summary>
			/// 	Exports all exportable parameter to file.
			/// </summary>
			///
			/// <param name="sxFilename"> The file name. </param>
			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			void ExportParameterToFile(const CRxString& sxFilename) const;

			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			/// <summary>
			/// 	Exports all exportable parameter to the given string by calling GetValue for each parameter.
			/// </summary>
			///
			/// <param name="sxXmlString"> [out] The XML string. </param>
			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			void ExportParameterToString(CRxString& sxXmlString) const;
		};
	}
}
