/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2014 Raytrix GmbH. All rights reserved.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once

#ifndef RX_STATIC
    #ifdef RXCOREEX_EXPORTS
		#define RXCOREEX_API __declspec(dllexport)
    #else
		#define RXCOREEX_API __declspec(dllimport)
    #endif
#else
	#define RXCOREEX_API
#endif

#include "RxImage.h"
#include "RxImageFormat.h"

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// namespace: Rx
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
namespace Rx
{
/**
        \addtogroup RxCore_Image Image classes
**/
/// @{

	/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	/// <summary>
	/// 	Image moniker class. Implements the interface Interop::Runtime28::IImage but does not allocate memory.
	///
	/// 	This class implements the basic functionality for an image, but does not create its own memory block. Instead, it can
	/// 	hold the pointer to an image memory block created by some other means. This class therefore does not free the memory
	/// 	the data pointer points to, when it is deleted.
	/// </summary>
	/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	class RXCOREEX_API CRxImageMoniker : public Interop::Runtime28::IImage
	{
	public:

		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>
		/// 	Default constructor.
		/// </summary>
		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		CRxImageMoniker();

		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>
		/// 	Constructor.
		/// </summary>
		///
		/// <param name="xMoniker">	The moniker. </param>
		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		CRxImageMoniker(const CRxImageMoniker& xMoniker);

		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>
		/// 	Move constructor.
		/// </summary>
		///
		/// <param name="xMoniker"> [in] The moniker to move. Is invalid after this call. </param>
		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		CRxImageMoniker(CRxImageMoniker&& xMoniker);

		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>
		/// 	Sets the internal image format to the given format and the internal data pointer to given data pointer.
		/// </summary>
		///
		/// <param name="xFormat"> The image format. </param>
		/// <param name="pvData">  (Optional) The image data pointer. </param>
		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		CRxImageMoniker(const CRxImageFormat& xFormat, const void* pvData = nullptr);

		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>
		/// 	Destructor.
		/// </summary>
		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		virtual ~CRxImageMoniker();

		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Assignment operator. </summary>
		///
		/// <param name="xMoniker">	The moniker. </param>
		///
		/// <returns>	A shallow copy of this CRxImageMoniker. </returns>
		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		CRxImageMoniker& operator=(const CRxImageMoniker& xMoniker);

		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>
		/// 	Move assignment operator.
		/// </summary>
		///
		/// <param name="xMoniker"> [in] The moniker to move. Is invalid after this call. </param>
		///
		/// <returns> A shallow copy of this object. </returns>
		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		CRxImageMoniker& operator=(CRxImageMoniker&& xMoniker);

	public:

		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>
		/// 	Creates an image moniker for given image.
		/// </summary>
		///
		/// <param name="pImage"> The image. </param>
		///
		/// <returns> True if it succeeds, false if it fails. </returns>
		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		virtual bool Create(const Interop::Runtime28::IImage* pImage);

		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>
		/// 	Sets image format data to given type and size. No memory is allocated and internal data pointer is set to zero.
		/// </summary>
		///
		/// <param name="iWidth">	  The width. </param>
		/// <param name="iHeight">    The weight. </param>
		/// <param name="ePixelType"> The pixel type. </param>
		/// <param name="eDataType">  The data type. </param>
		///
		/// <returns> True if it succeeds, false if it fails. </returns>
		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		virtual bool Create(int iWidth, int iHeight, Interop::Runtime28::EPixelType::ID ePixelType, Interop::Runtime28::EDataType::ID eDataType);

		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>
		/// 	Sets image format to given type and size and set internal data pointer to given data pointer.
		/// </summary>
		///
		/// <param name="iWidth">	  The width. </param>
		/// <param name="iHeight">    The weight. </param>
		/// <param name="ePixelType"> The pixel type. </param>
		/// <param name="eDataType">  The data type. </param>
		/// <param name="pvData">	  The data pointer. </param>
		///
		/// <returns> True if it succeeds, false if it fails. </returns>
		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		virtual bool Create(int iWidth, int iHeight, Interop::Runtime28::EPixelType::ID ePixelType, Interop::Runtime28::EDataType::ID eDataType, const void* pvData);

	public:

		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>
		/// 	Sets image format to given type and size and set internal data pointer to given data pointer.
		/// </summary>
		///
		/// <param name="iWidth">	  The width. </param>
		/// <param name="iHeight">    The weight. </param>
		/// <param name="iPixelType"> The pixel type. </param>
		/// <param name="iDataType">  The data type. </param>
		/// <param name="pvData">	  (Optional) The data pointer. </param>
		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		void Create(int iWidth, int iHeight, int iPixelType, int iDataType, const void* pvData = nullptr);

		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>
		/// 	Sets the internal image format to the given format and the internal data pointer to given data pointer.
		/// </summary>
		///
		/// <param name="xFormat"> The image format. </param>
		/// <param name="pvData">  (Optional) The data pointer. </param>
		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		void Create(const CRxImageFormat& xFormat, const void* pvData = nullptr);

		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>
		/// 	Sets image format to image format of given image and set internal data pointer to data pointer of given image.
		/// </summary>
		///
		/// <param name="xImage">	The image. </param>
		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		void Create(const CRxImage& xImage);

	public:

		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>
		/// 	Sets internal data pointer to zero and reset image format data.
		/// </summary>
		///
		/// <returns>	True if it succeeds, false if it fails. </returns>
		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		virtual bool Destroy();

		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>
		/// 	Sets internal data pointer to given data pointer.
		/// </summary>
		///
		/// <param name="pvData">	The data pointer. </param>
		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		void Set(const void* pvData);

		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>
		/// 	Tests whether data pointer is not zero.
		/// </summary>
		///
		/// <returns>	True if valid, false if not. </returns>
		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		virtual bool IsValid() const
		{
			return m_pvData != 0;
		}

		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>
		/// 	Gets number of bytes per pixel.
		/// </summary>
		///
		/// <returns>	The bytes per pixel. </returns>
		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		virtual int GetBytesPerPixel() const
		{
			return m_xFormat.GetBytesPerPixel();
		}

		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>
		/// 	Gets the number of pixels.
		/// </summary>
		///
		/// <returns>	The pixel count. </returns>
		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		virtual unsigned GetPixelCount() const
		{
			return m_xFormat.GetPixelCount();
		}

		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>
		/// 	Gets the number of bytes of the whole image.
		/// </summary>
		///
		/// <returns>	The byte count. </returns>
		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		virtual unsigned GetByteCount() const
		{
			return m_xFormat.GetByteCount();
		}

		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>
		/// 	Gets the image format.
		/// </summary>
		///
		/// <returns>	The format. </returns>
		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		const CRxImageFormat& GetFormat() const
		{
			return m_xFormat;
		}

		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>
		/// 	Returns the pointer to the data array.
		/// </summary>
		///
		/// <returns>	Null if it fails, else the data pointer. </returns>
		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		virtual void* GetDataPtr()
		{
			return m_pvData;
		}

		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>
		/// 	Returns the constant pointer to the data array.
		/// </summary>
		///
		/// <returns>	Null if it fails, else the data pointer. </returns>
		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		virtual const void* GetDataPtr() const
		{
			return m_pvData;
		}

		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>
		/// 	Gets width and height of image.
		/// </summary>
		///
		/// <param name="iWidth"> 	[out] The width. </param>
		/// <param name="iHeight">	[out] The height. </param>
		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		virtual void GetSize(int& iWidth, int& iHeight) const
		{
			iWidth  = m_xFormat.m_iWidth;
			iHeight = m_xFormat.m_iHeight;
		}

		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>
		/// 	Gets pixel and data type of image.
		/// </summary>
		///
		/// <param name="iPixelType">	[out] The pixel type. </param>
		/// <param name="iDataType"> 	[out] The data type. </param>
		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		virtual void GetType(int& iPixelType, int& iDataType) const
		{
			iPixelType = int(m_xFormat.m_ePixelType);
			iDataType  = int(m_xFormat.m_eDataType);
		}

		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>
		/// 	Gets pixel and data type of image.
		/// </summary>
		///
		/// <param name="ePixelType">	[out] The pixel type. </param>
		/// <param name="eDataType"> 	[out] The data type. </param>
		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		void GetType(Interop::Runtime28::EPixelType::ID& ePixelType, Interop::Runtime28::EDataType::ID& eDataType) const
		{
			ePixelType = m_xFormat.m_ePixelType;
			eDataType  = m_xFormat.m_eDataType;
		}

		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>
		/// 	Tests whether image is of a particular pixel and data type.
		/// </summary>
		///
		/// <param name="ePixelType">	The pixel type. </param>
		/// <param name="eDataType"> 	The data type. </param>
		///
		/// <returns>	True if of type, false if not. </returns>
		/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		bool IsOfType(Interop::Runtime28::EPixelType::ID ePixelType, Interop::Runtime28::EDataType::ID eDataType) const
		{
			return ePixelType == m_xFormat.m_ePixelType && eDataType == m_xFormat.m_eDataType;
		}

	protected:

		CRxImageFormat m_xFormat;
		void* m_pvData;
	};

	/// @}
}
