/**
 * @file
 * @brief 画面描画（スプライト・背景画像）の実装を行う.
 *
 * @author S.F.
 * @version $Id:
 *
 * Copyright (C) 2000-2002 Satoshi Fujiwara. All Rights Reserved.
 */

/// 重複インクルード防止マクロ
#if !defined(AFX_ConsoleImpl_H__B6F6F87A_C87F_40DA_8F4F_C037111CAC9D__INCLUDED_)
#define AFX_ConsoleImpl_H__B6F6F87A_C87F_40DA_8F4F_C037111CAC9D__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include "sf.h"
#include "Console.h"
extern "C" {
namespace sf { 
	namespace system {
		namespace console {
			/// スプライト用 バーテックスバッファのフラグ 
			const DWORD VertexFVF = 
				(D3DFVF_XYZRHW | ///< 座標系
				D3DFVF_DIFFUSE | ///< ディフューズ
				D3DFVF_SPECULAR	| ///< スペキュラ
				D3DFVF_TEX1 );

			/// 3Dカスタム頂点フォーマット
			struct Vertex2 {
			    D3DVECTOR position;	///< オブジェクト座標。
				DWORD   diffuse; ///< ディフューズ
				DWORD	specular;///< スペキュラ成分
				float   tu;///< テクスチャu座標
				float   tv;///< テクスチャv座標
			};

			/// 3Dスプライト用 バーテックスバッファのフラグ 
			const DWORD Vertex2FVF = (D3DFVF_DIFFUSE |  D3DFVF_SPECULAR | D3DFVF_XYZ | D3DFVF_TEX1);
	
			/** Consoleインターフェースの実装. */
			class ConsoleImpl : public Console  
			{
				// LIFECYCLE //
			public:
				/// コンストラクタ
				ConsoleImpl();
				/** コンストラクタ
				* @param hwnd ウィンドウハンドル
				* @param bWindow ウィンドウ表示かフルスクリーン表示か */
				ConsoleImpl(const HWND hwnd,const bool bWindow);
				/// デストラクタ				
				virtual ~ConsoleImpl();
				// OPERATORS //
				// OPERATIONS //
				virtual void initialize(void);
				/** 初期化を行う.
				 * @param hwnd ウィンドウハンドル
				 * @param bWindow true ウィンドウ表示 false フルスクリーン表示 */
				void initialize(const HWND hwnd,const bool bWindow);

				/** 終了処理を行う.
				 * 終了時に開放しなくてはいけないものはここで開放する */
				void uninitialize(void);

				virtual void clearScreen(COLOR value = 0x00000000);
				virtual void fillScreen(COLOR value = 0x00000000);
				void update(void);
				
				// バックバッファにAscii文字列を指定したテクスチャー番号で表示する。
				virtual void print(const int textureNo,const float x,const float y,const float angleRad,const float scale,const COLOR color,
					const char *format,...);
				// スプライトのロード
				sprite::Sprite* const createSprite(const sprite::Info* const pInfo);

				// ACCESS //

				// INQUIRY //
				virtual const bool isEnabled(void) const {return mbD3DReady;};

			private:
				/** D3Dデバイスをチェックし、選択する.
				 * 現在のハードウェアのD3Dデバイスをチェックし、ConsoleImplが必要とする要求に対応し、もっとも能力の高いものを選択します。*/
				void checkAndSetDevice(const D3DDEVTYPE devtype = D3DDEVTYPE_HAL);

				/** デバイスタイプをチェックし、設定する */
				void checkAndSetDeviceType(const D3DDEVTYPE devtype);
	
				/** 現在のハードウェアのバックバッファフォーマットをチェックし、設定する
				 * システムが要求するバックバッファフォーマットがあるかどうかチェックし、あれば設定します。<br>
				 * なければ、要求するものに最も近いバックバッファのフォーマットを選択します */
				void checkAndSetBackBufferFormat(void);
				/** 現在のハードウェアのテクスチャフォーマットをチェックし、設定する */
				void checkAndSetTextureFormat(void);
				/** 現在のハードウェアのビット深度を調べて、設定する */
				void checkAndSetDepthFormat(void);
				
				/// レンダリングステート、テクスチャステージステートの初期化を行う
				void initDeviceStates(void);

				/// 画面の初期化・ビューポートの設定などを行う 
				void initConsoleViewStyle(void);
				
				/// ライトの初期化を行う
				void initLight();

				/// 変換行列の初期化を行う
				void initMatrix();


				/// Reset時に再作成しなくてはいけない処理を行う
				void initNotManagedObjects(void);

				/// D3DDeviceで管理されないオブジェクトを開放する
				void releaseNotManagedObjects(void);
				
				/// フォントファイルを読み込む
				void loadFont(void);

				/// フレーム開始を宣言する
				void startFrame(void);

				/// フレーム終了を宣言する
				void endFrame(void);

				/// テキストの描画を行う
				void textDraw(int textureNo,float x,float y,float angleRad,float scale,COLOR color,char *pBuf);

				/// テキストキューの内容を出力する
				void textOut(void);

				HWND	mhWndMain;///< Windowハンドル
				
				bool					mbD3DReady;///< すべての初期化が完了し、使用可能
				bool					mbWindowed;	///< ウィンドウモードかどうか
				
				LPDIRECT3D9				mpD3D;///< D3D
				D3DDEVTYPE				mD3DDeviceType;///< D3Dデバイスタイプ									
				
				LPDIRECT3DDEVICE9		mpD3DDevice;///< D3DDevice
				LPD3DXSPRITE			mpD3DXSprite;///< D3DXSprite
				
				D3DFORMAT				mD3DFormat;///< プライマリ・バックバッファのフォーマット
				D3DFORMAT				mTextureFormat;///< 透過テクスチャ用フォーマット
				D3DFORMAT				mDepthFormat;///<　深度バッファ用フォーマット
				D3DPRESENT_PARAMETERS	mD3Dpp;///< D3DPRESENT_PARAMETERS
				
				IDirect3DTexture9* 		mpFontTexture[font::COUNT_MAX];///< フォントテクスチャ配列
				sprite::AbstractSprite* mpSprite[sprite::MAX];///< スプライトテクスチャ配列
				
				///　テキスト文字列保持クラス
				class TextQueueData{
				public:
					/**　コンストラクタ 
					 * @param テクスチャ番号
					 * @param x 表示x座標
					 * @param y 表示y座標
					 * @param angleRad 表示角度(ラジアン)
					 * @param scale 拡大縮小率
					 * @param color 表示色
					 * @param pBuffer テキスト文字列のポインタ */
					TextQueueData(const int textureNo,const float x,const float y,const float angleRad,const float scale,const COLOR color,const char *pBuffer = NULL);
					/// デストラクタ
					~TextQueueData();
					// ACCESS 
					/** テキスト文字列のポインタを取得する.
					 * @return テキスト文字列の先頭アドレス */
					char * const buffer(void) { return mpBuf;};
					
					/** フォントテクスチャ番号を取得する.
					 * @return フォントテクスチャ番号 */
					const int textureNo() const { return mTextureNo;};
					
					/** 表示開始X座標を取得する.
					 * @return 表示開始X座標 */
					const float x() const { return mX;};

					/** 表示開始Y座標を取得する.
					 * @return 表示開始Y座標 */
					const float y() const { return mY;};

					/** 表示角度を取得する.
					 * @return 表示開始X座標 */
					const float angeleRad() const { return mAngleRad;};

					/** 拡大縮小率を取得する.
					 * @return 拡大縮小率 */
					const float scale() const { return mScale;};

					/** 表示色を取得する.
					 * @return 表示色 */
					const COLOR color() const { return mColor;};
				private:
					int mTextureNo;///< フォントテクスチャ番号
					float mX;///< 表示開始X座標
					float mY;///< 表示開始Y座標
					float mAngleRad;///< 表示角度（ラジアン）
					float mScale;///< 拡大縮小率
					COLOR mColor;///< 表示色
					char mpBuf[text::BUFFER_LENGTH];///< 表示文字列
				};

				/// テキスト表示用キューバッファ 
				std::queue<TextQueueData *> mTextQueue;

			}; // ConsoleImpl
		} // namespace console
	} // namespace system
} // namespace sf
}
#endif // !defined(AFX_ConsoleImpl_H__B6F6F87A_C87F_40DA_8F4F_C037111CAC9D__INCLUDED_)
