/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2014 Raytrix GmbH. All rights reserved.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once

#ifndef RX_STATIC
    #ifdef RXINTEROP30_EXPORTS
		#define RXINTEROP30_API __declspec(dllexport)
    #else
		#define RXINTEROP30_API __declspec(dllimport)
    #endif
#else
	#define RXINTEROP30_API
#endif

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// namespace: Rx.Interop.Runtime30
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
namespace Rx
{
	namespace Interop
	{
		namespace Runtime30
		{
			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			/// <summary>
			/// 	Interface for memory read operations.
			/// </summary>
			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			class RXINTEROP30_API IMemoryAccess
			{
			public:

				/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
				/// <summary>
				/// 	Gets the element size. The memory block is made up of blocks of the given number of bytes. The function Length()
				/// 	returns the number of elements in the memory block, where each element is of the size given in GetElementSize(). For
				/// 	example, an array of 10 doubles has element size 8 and length 10.
				/// </summary>
				///
				/// <returns> The element size in bytes. </returns>
				/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
				virtual size_t GetElementSize() const = 0;

				/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
				/// <summary>
				/// 	Gets the number of elements in the memory block. The total number of bytes allocated by the memory block is given by
				/// 	the length times the element size.
				/// </summary>
				///
				/// <returns> The size in bytes. </returns>
				/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
				virtual size_t Length() const = 0;

				/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
				/// <summary>
				/// 	Gets the pointer to memory.
				/// </summary>
				///
				/// <returns> The pointer to memory. </returns>
				/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
				virtual const void* GetPointer() const = 0;

				/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
				/// <summary>
				/// 	Query if this object is valid. This function returns also true if the object itself is valid but the memory block has
				/// 	size zero.
				/// </summary>
				///
				/// <returns> True if valid, false if not. </returns>
				/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
				virtual bool IsValid() const = 0;

			protected:

				/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
				/// <summary>
				/// 	Destructor.
				/// </summary>
				/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
				virtual ~IMemoryAccess()
				{
				}
			};

			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			/// <summary>
			/// 	Common memory interface.
			/// </summary>
			/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			class RXINTEROP30_API IMemory : public IMemoryAccess
			{
			public:

				/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
				/// <summary>
				/// 	Creates a new memory block of \a nElementCount elements. The size of an element is fixed by the implementation and can
				/// 	be read out with the function GetElementSize().
				/// </summary>
				///
				/// <param name="nElementCount"> The new number of elements stored in the memory block. </param>
				/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
				virtual void New(size_t nElementCount) = 0;

				/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
				/// <summary>
				/// 	Resizes the memory block to the given number of elements. The size of an element is fixed by the implementation and can
				/// 	be read out with the function GetElementSize().
				/// </summary>
				///
				/// <param name="nNewElementCount"> The new number of elements stored in the memory block. </param>
				/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
				virtual void Resize(size_t nNewElementCount) = 0;

				/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
				/// <summary>
				/// 	Deletes this memory block.
				/// </summary>
				/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
				virtual void Delete() = 0;

				/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
				/// <summary>
				/// 	Reset all values in the memory block. The actual value the elements in the memory block are reset to depends on the
				/// 	implementation.
				/// </summary>
				/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
				virtual void Reset() = 0;

				/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
				/// <summary>
				/// 	Copies the memory block described by pMemory into this memory block. This memory block is automatically resized. The
				/// 	function throws an exception if the element sizes of the given memory block does not agree with the element size of
				/// 	this memory block.
				/// </summary>
				///
				/// <param name="pMemory"> [in] The memory to copy into this memory block. </param>
				/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
				virtual void CopyFrom(const IMemoryAccess* pMemory) = 0;

				// Tell the compiler we want both the GetPointer() from base, which is a const function and this one here which returns
				// a non-const pointer.
				using IMemoryAccess::GetPointer;

				/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
				/// <summary>
				/// 	Gets the pointer to the memory block.
				/// </summary>
				///
				/// <returns> The pointer to memory. </returns>
				/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
				virtual void* GetPointer() = 0;

			protected:

				/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
				/// <summary>
				/// 	Destructor.
				/// </summary>
				/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
				virtual ~IMemory()
				{
				}
			};
		}
	}
}
