#ifndef CSurfaceBuffer_h
#define CSurfaceBuffer_h

#include"../../../Setup/CompileMode.h"
#include"../../../template/Mathematics.h"
#include"../../CSurfaceInfo.h"
#include"../../Color.h"

#include<boost/smart_ptr.hpp>

namespace Maid
{

	/*!
	 	@class	ISurfaceBufferInfo CSurfaceBuffer.h
	 	@brief	サーフェスの情報を表す構造体
	\n			ISurfaceBuffer::Lock() でこのクラスを取得します
	 
	 */
	class ISurfaceBufferInfo
	{
	public:
		virtual ~ISurfaceBufferInfo(){}	//!<	デストラクタ

		//! 各ラインの先頭アドレスの取得
		/*! 
		 	@param	PosY	[i ]	取得したいライン( PosY<GetHeight() であること）
		 
		 	@return 指定したラインアドレス
		 */
		virtual void* GetLinePtr( int PosY )const=0;

		void* GetPixelPtr( int PosX, int PosY ) const;

		//! サーフェスの先頭アドレスの取得
		/*! 
		 	このアドレスが座標(0,0)のアドレスであるとは限りません（圧縮サーフェス等）
		 
		 	@return サーフェスの先頭アドレス
		 */
		virtual void* GetAddress() const=0;

		//! カラールックアップテーブル（いわゆるパレット）の取得
		/*! 
		 	@return パレットの先頭アドレス
		 */
		virtual void* GetCLUT() const=0;

		//! サーフェスの横幅の取得
		/*! 作成されているサーフェスの横幅を取得します
		\n	ISurface::GetWidth() と同じです
		 
		 	@return サーフェスの横幅
		 */
		virtual int		GetWidth() const=0;
		//! サーフェスの縦幅の取得
		/*! 作成されているサーフェスの縦幅を取得します
		\n	ISurface::GetHeight() と同じです
		 
		 	@return サーフェスの縦幅
		 */
		virtual int		GetHeight() const=0;


		//! サーフェスのピクセルフォーマットの取得
		/*! 作成されているサーフェスのピクセルフォーマットを取得します
		 
		 	@return サーフェスのピクセルフォーマット
		 */
		virtual PIXELFORMAT GetPixelFormat() const=0;

		//! サーフェスのピッチの取得
		/*! 
		 	@return サーフェスのピッチ
		 */
		virtual int		GetPitch() const=0;


		COLOR_A08R08G08B08I GetPixel( int x, int y );
		void SetPixel( int x, int y, const COLOR_A08R08G08B08I& col );
	};

	typedef boost::shared_ptr<ISurfaceBufferInfo>	SPSURFACEBUFFERINFO;


	/*!
	 	@class	ISurfaceBuffer CSurfaceBuffer.h
	 	@brief	サーフェスバッファの基本クラス
	 */
	class ISurfaceBuffer
	{
	public:
		virtual ~ISurfaceBuffer(){}	//!<	デストラクタ

		//! サーフェスの大きさの取得
		/*! 
		 	@return	サーフェスの横幅、縦幅
		 */
		virtual SIZE2DI GetSize() const=0;


		//! ピクセルフォーマットの取得
		/*! 
		 	@return	ピクセルフォーマット
		 */
		virtual PIXELFORMAT GetPixelFormat() const=0;

		//! サーフェスのロック
		/*!
		 	サーフェスの内部アドレスにアクセスできるようにします
		\n	Lock() を呼び出した場合は必ず Unlock() も呼び出すようにすること
		\n	CSurfaceLoacker を使うと便利です
		 
		 	@param	info	[ o]	ロックに成功するとこれに各種情報が入る
		 */
		virtual void Lock( SPSURFACEBUFFERINFO& info )=0;

		//! サーフェスのアンロック
		/*!
		 	Lock()　でロックしたサーフェスを再び使えるようにアンロックします
		\n	CSurfaceLoacker を使うと便利です
		 */
		virtual void Unlock()=0;

	};

	typedef boost::shared_ptr<ISurfaceBuffer> SPSURFACEBUFFER;
	typedef boost::shared_ptr<const ISurfaceBuffer> SPCONSTSURFACEBUFFER;



	/*!
	 	@class	CSurfaceBufferLoacker DenSurfaceBuffer.h
	 	@brief	ISurfaceBuffer::Lock(), ISurfaceBuffer::Unlock() を
	\n			自動的に行うクラス
	 
	 	@code
		{
			SPSURFACEBUFFER pSurface( new ISurfaceXXXXX );
			SPSURFACEBUFFERINFO pinfo;

			CSurfaceLoacker lock( pSurface.get(), pinfo  );	//	これでロックされる

			//	ここでいろいろ行う	

		}	//	lock のデストラクタで pSurface->Unlock() される
		
	 	@endcode
	 */
	class CSurfaceBufferLoacker
	{
	public:

		CSurfaceBufferLoacker( ISurfaceBuffer& Surface, SPSURFACEBUFFERINFO& info )
			: m_Surface( Surface )
		{
			m_Surface.Lock( info );
		}

		~CSurfaceBufferLoacker()	//!<	デストラクタ
		{
			m_Surface.Unlock();
		}
	private:
		ISurfaceBuffer& m_Surface;
	};
}


#endif