/**
 * DrawParam_D3D.h
 *
 *  Copyright(c) Live2D Inc. All rights reserved.
 *  [[ CONFIDENTIAL ]]
 */
#ifndef __LIVE2D_DRAWPARAM_D3D_H__
#define __LIVE2D_DRAWPARAM_D3D_H__

#ifndef __SKIP_DOC__

#include "Live2D.h"

#ifdef L2D_TARGET_D3D

#include "type/LDVector.h"
#include <d3dx9.h>
#include "graphics/DrawParam.h"
#include "type/LDMap.h"
//------------ LIVE2D NAMESPACE ------------
namespace live2d
{ 
	// 頂点座標専用の構造体
	typedef struct LIVE2D_D3D_VERTEX
	{
		D3DXVECTOR3 Position;
	} LIVE2D_D3D_VERTEX;


	// UVデータ専用の構造体
	typedef struct LIVE2D_D3D_UV
	{
		D3DXVECTOR2 Texture;
	} LIVE2D_D3D_UV;


	/**********************************************************************************
	@brief		DirectX用の描画クラス
	************************************************************************************/
	class DrawParam_D3D : public DrawParam 
	{
	public:
		static const int INITIAL_VERTEX_COUNT = 300;		
		static const int INITIAL_INDEX_COUNT = 150;			
		
		//--- error / Direct3D is 6000.. ---
		static const int ERROR_D3D_CREATE_VERTEX_BUFFER	= 6001;
		static const int ERROR_D3D_LOCK_VERTEX_BUFFER	= 6002;
		static const int ERROR_D3D_CREATE_INDEX_BUFFER	= 6003;
		static const int ERROR_D3D_LOCK_INDEX_BUFFER	= 6004;
		static const int ERROR_D3D_DEVICE_NOT_SET		= 6005;
		static const int ERROR_D3D_LOAD_SHADER			= 6006;

		// デバイスセット
		static void setDevice( LPDIRECT3DDEVICE9 device );

		// クリッピングマスク用のテクスチャを設定する
		static void setMaskTexture(LPDIRECT3DTEXTURE9 maskTexture);

		// クリッピングマスク用のサーフェースを設定する
		static void setMaskSurface(LPDIRECT3DSURFACE9 maskSurface);

		// デバイスロストした時に共通して呼び出す
		static void deviceLostCommon();

		// デバイスリセットした時に共通して呼び出す
		static void deviceResetCommon();

		// シェーダのロード
		static HRESULT initShader();

		// 共有リソースの破棄
		static void dispose();

	public:
		DrawParam_D3D();
		virtual ~DrawParam_D3D();
		
	public:
		virtual void deleteTextures() ;

		virtual void setupDraw() ;

		void drawTextureD3D( int textureNo , int indexCount , int vertexCount , l2d_index * indexArray 
								, l2d_pointf * vertexArray , l2d_uvmapf * uvArray , float opacity
								, LPDIRECT3DVERTEXBUFFER9 pUvBu // Uv配列
								, LPDIRECT3DINDEXBUFFER9 pIndexBuf // インデックス配列
								, int colorCompositionType // 色合成のタイプ
							 ) ;

		void drawTexture( int textureNo , int indexCount , int vertexCount , l2d_index * indexArray 
			, l2d_pointf * vertexArray , l2d_uvmapf * uvArray , float opacity
			, int colorCompositionType // 色合成のタイプ
			) ;

	
		void setTexture( int modelTextureNo , LPDIRECT3DTEXTURE9 textureNo ) ;

		//  新しく利用できるModelのテクスチャ番号を確保(Avatar用）
		virtual int generateModelTextureNo() ;
		
		//  Modelのテクスチャ番号を生成(Avatar用）
		virtual void releaseModelTextureNo(int no) ;
		
		/********************************************************************
		@brief		前回getErrorで呼んだ後で発生したエラーを取得する
		**********************************************************************/
		int getErrorD3D_tmp()
		{
			int ret = error ;
			error = 0 ;
			return ret ;
		}


		/********************************************************************
		@brief		エラー
		@param		error	->	エラー番号
		**********************************************************************/
		void setErrorD3D_tmp( int error ){ this->error = error ; }
		

		/********************************************************************
		@brief		デバイス取得
		@return		設定されているデバイスデータ
		**********************************************************************/
		LPDIRECT3DDEVICE9 getDevice(){ return pd3dDevice ; }


		/********************************************************************
		@brief		D3DのUVバッファのセット
		**********************************************************************/
		void setUpBufD3D_UV(int vertexCount_, l2d_uvmapf*	uvArray);

		/********************************************************************
		@brief		D3DのIndexバッファのセット
		**********************************************************************/
		void setUpBufD3D_Index(int indexCount, l2d_index* indexArray);





		//  DirectXデバイスロスト時に呼び出す
		void deviceLost( ) ;


		//  DirectX用点列メモリ確保（DDTexture側から呼ばれる）
		static HRESULT createUvBuffer(    LPDIRECT3DDEVICE9 pd3dDevice , unsigned int length , IDirect3DVertexBuffer9**  ppVerterxBuffer ) ;
		static HRESULT createIndexBuffer( LPDIRECT3DDEVICE9 pd3dDevice , unsigned int length , IDirect3DIndexBuffer9**   ppIndexBuffer ) ;


	private:
		// Prevention of copy Constructor
		DrawParam_D3D( const DrawParam_D3D & ) ;
		DrawParam_D3D& operator=( const DrawParam_D3D & ) ; 
		
	private:
		// 描画ブレンドモード
		// (値はRenderEffectのPassに紐づく)
		enum RENDER_EFFECT_BLEND_MODE
		{
			RENDER_EFFECT_BLEND_MODE_MULT         = 0, // 乗算
			RENDER_EFFECT_BLEND_MODE_ADD          = 1, // 加算
			RENDER_EFFECT_BLEND_MODE_INTERPORATE  = 2, // 補間
		};

		// RenderEffectのグローバル変数のハンドル一覧
		struct EffectConstantHandleTable
		{
			D3DXHANDLE techNormal;				// 通常描画
			D3DXHANDLE techNormalPremultiplied;	// 乗算済みアルファ＋通常描画
			D3DXHANDLE techMask;				// クリッピングマスク描画
			D3DXHANDLE techMaskPremultiplied;	// 乗算済みアルファ＋クリッピングマスク描画
			D3DXHANDLE worldViewProj;
			D3DXHANDLE baseColor;
			D3DXHANDLE interpolate;
			D3DXHANDLE windowWidth;
			D3DXHANDLE windowHeight;
		};

		//--------- fields ------------
		LDVector<LPDIRECT3DTEXTURE9>	textures ;			// Destructorでテクスチャの解放は行わない。基本的に外部で行う。

		LPDIRECT3DVERTEXBUFFER9			pVertexBuf ;		// 頂点配列
		int								vertexBuf_length ;	// 現在のBufferのサイズ

		IDirect3DVertexDeclaration9*	pDec ;				// 頂点定義

		live2d::LDMap<DrawDataID*,LPDIRECT3DVERTEXBUFFER9>  pUVBufMap;//UV配列のDDTEXTURE毎のマップ
		live2d::LDMap<DrawDataID*,LPDIRECT3DINDEXBUFFER9>   pIndexBufMap;//インデックス配列のDDTEXTURE毎のマップ

		live2d::LDVector<DrawDataID*>                       pDrawDataIDs;//描画データのIDのポインタを管理する  現状LDMapの要素を削除するためにしか使っていない


		//-- error
		int								error ;				// エラー記録用。将来的には基底クラスに移動予定

	private:
		static LPDIRECT3DDEVICE9		pd3dDevice ;		// DirectXデバイスを保持
		static LPDIRECT3DSURFACE9		pMainSurface;		// モデルの描画先
		static LPDIRECT3DSURFACE9		pMaskSurface;		// クリッピングマスクのサーフェース
		static LPDIRECT3DTEXTURE9		pMaskTexture;		// クリッピングマスクのテクスチャ
		static LPD3DXEFFECT				pRenderEffect;		// 通常描画、クリッピングを含むシェーダ
		static EffectConstantHandleTable effectHandleTable; // RenderEffectのグローバル変数のハンドル一覧
	};

} 
//------------ LIVE2D NAMESPACE ------------
#endif// L2D_TARGET_D3D

#endif // __SKIP_DOC__

#endif		// __LIVE2D_DRAWPARAM_D3D_H__