/**
 * @file Console.h
 * @brief 画面描画（スプライト・背景画像）のインターフェース・定数定義を行う.
 * 画面関連の定数定義
 * 実際の処理は、OS依存の具象クラスに任せます。
 * 2000/02/18 ぷよーんさんのライブラリを参考に３Ｄ部分を追加
 *
 * @author S.F.
 * @version $Id:
 *
 * Copyright (C) 2000-2002 Satoshi Fujiwara. All Rights Reserved.
 */
 
/// 二重インクルード防止マクロ
#if !defined(AFX_IConsole_H__DB7BCF98_4A51_43E3_B919_9A26C58E6A90__INCLUDED_)
#define AFX_IConsole_H__DB7BCF98_4A51_43E3_B919_9A26C58E6A90__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include <memory>

#include "sf.h"

extern "C" {
namespace sf{
	namespace system {
		/// 画面関連のクラス・定数
		/*! 画面関連のクラス・定数はすべてのこの名前空間に含まれます。 */
		namespace console {
			/// カラー型の定義
			typedef unsigned long COLOR;
			
/** R,G,B,Aの各色から、32bitの値を得る 
 * Red,Green,Blue,Alphaの各色成分(8bit)をもとに、32bitのlong値を生成します 
 * @param a ALPHA成分
 * @param r RED成分
 * @param g GREEN成分
 * @param b BLUE成分 */
#define COLOR(a,r,g,b) ((COLOR)((((a) & 0xff) << 24 )) | (((r) & 0xff) << 16) | (((g) & 0xff) << 8) | ((b) & 0xff)))

			/** RGBカラーを制御するクラス. 
			 * 32bitカラーの値から、各色成分を取り出したり、各色成分を独立して操作するために作成されたクラスですが、あまり使われていません。
			*/
			class Color {
			public:
				Color() { mColor.value32 = 0;};
				/** コンストラクタその２ *
				 * @param xolor COLOR 型の値 */
				Color(COLOR color){mColor.value32 = color;};
				/** COLORの値を取り出す.
				 * @return COLOR型の値 */
				COLOR value(void) const {return mColor.value32;};
				/** COLORをセットする 
				 * @param color COLOR型の値 */
				void value(COLOR color){mColor.value32 = color;};

				/** 赤の成分を取得する 
				 * @return 赤成分(0-255) */
				unsigned char red(void) const { return mColor.value.red;};
				/** 赤の成分をセットする 
				 * @param value 赤成分(0-255) */
				void red(unsigned char value) { mColor.value.red = value;};

				/** 青の成分を取得する 
				 * @return 青成分(0-255) */
				unsigned char blue(void) const { return mColor.value.blue;};
				/** 青の成分をセットする 
				 * @param value 青成分(0-255) */
				void blue(unsigned char value) { mColor.value.blue = value;};
				
				/** 緑の成分を取得する 
				 * @return 緑成分(0-255) */
				unsigned char green(void) const { return mColor.value.green;};
				/** 緑の成分をセットする 
				 * @param value 緑成分(0-255) */
				void green(unsigned char value){mColor.value.green = value;};
				
				/** ALPHAの成分を取得する 
				 * @return ALPHA成分(0-255) */
				unsigned char alpha(void) const { return mColor.value.alpha;};
				/** ALPHAの成分をセットする 
				 * @param value ALPHA成分(0-255) */
				void alpha(unsigned char value){mColor.value.alpha = value;};

			private:
				///　無名共用体
				union {
					COLOR value32;///< ARGBの値(32bit)
					/// 無名構造体
					struct {
						unsigned char blue 	:	8;///< 青成分
						unsigned char green :	8;///< 緑成分
						unsigned char red	:	8;///< 赤成分
						unsigned char alpha	:	8;///< ALPHA成分
					} value;
					
				} mColor;
			};

			/// スクリーン関連
			namespace screen {
				const int WIDTH  = 640;///< スクリーンの幅
				const int HEIGHT = 480;///< スクリーンの高さ
			};
			
			/// ビューポート関連 
			namespace viewport {
				const int X = 120;	///< ビューポート左端 X
				const int Y = 0;	///< ビューポート左端 Y
				const float Z_MIN = 0.0f;///< ビューポートＺ最小
				const float Z_MAX = 1.0f;///< ビューポートＺ最大	
				const int WIDTH = 400;///< ビューポートの幅
				const int HEIGHT = 480;///< ビューポートの高さ
			};
			
			const int TEXTURE_COUNT_MIN = 0;///< テクスチャー数の最小値
			const int TEXTURE_COUNT_MAX = 1024;///< テクスチャー数の最大値

			// スプライト

			class ObjQuadrangle;
			class ObjRectangle;
			class Obj3DL;


			/// スプライト関連
			namespace sprite {
				const int MIN = 0;	///< スプライト数最小値？
				const int MAX = 1024; ///< スプライト数最大値
	
				/// スプライトのタイプ
				enum TYPE
				{
					SPRITE2D,///< 2Dスプライトである(座標が2D)
					SPRITE3D,///< 3Dスプライトである(座標が3D)
					MESH ///< メッシュである(Xファイル)
				};

				/** スプライト定義情報構造体.
				* スプライトを定義するための構造体です。
				* スプライトの生成は、Console インターフェースのConsole::createSprite()の引数としてこの構造体を渡し行います。*/
				struct Info {
					char fileName[_MAX_PATH];///< ビットマップファイルネーム
					float centerX;///< 中心のX座標
					float centerY;///< 中心のY座標
					float cellWidth;///< 幅
					float cellHeight;///< 高さ
					COLOR transparentColor;///< 透過色
					TYPE type;///< スプライトのタイプ
				};

			
				/** スプライトの描画制御を行う. 
				 * 実際のスプライト描画を行うインターフェースです。
				 * ObjRectangleなどの座標を保持するクラスを引数に画面に自身が保持しているビットマップを画面に描画します。
				 * @Section SpriteインターフェースとObjインターフェースの関係について.
				 * @para ObjインターフェースとSpriteインターフェースの関係
				 * console::Spriteは、テクスチャのビットマップ、uv座標を保持し、console::Objの継承クラスに応じたconsole::Sprite::draw()メソッドを持ちます。<br>
 				 * console::Objは、console::Spriteを画面上どのように表示するのかを指定するためのインターフェースです*/
				class Sprite
				{
				public:
					/// デストラクタ
					virtual ~Sprite(){;};
					/** ObjRectangle を引数にスプライトを描画します. 
					 * @param pObj ObjRectangleクラスへのポインタ */
					virtual void draw(const sf::system::console::ObjRectangle * const pObj) = 0;
					/** ObjQuadrangle を引数にスプライトを描画します. 
					 * @param pObj ObjQuadrangleクラスへのポインタ */
					virtual void draw(const sf::system::console::ObjQuadrangle * const pObj) = 0;
					/** Obj3DL を引数にスプライトを描画します. 
					 * @param pObj Obj3DL クラスへのポインタ */
					virtual void draw(const sf::system::console::Obj3DL * const pObj) = 0;
					/** スプライトの中心X座標を取得する.
					 * @return スプライトの中心X座標 */
					virtual const float centerX(void) const = 0;
					/** スプライトの中心Y座標を取得する.
					 * @return スプライトの中心Y座標 */
					virtual const float centerY(void) const  = 0;
					/** スプライトの幅を取得する.
					 * @return スプライトの幅 */
					virtual const float width(void) const = 0;
					/** スプライトの中心高さを取得する.
					 * @return スプライトの高さ */
					virtual const float height(void) const = 0;
				};// Sprite
				
				/// Spriteのスマートポインタ 
				typedef std::auto_ptr<Sprite> PSprite;

			};
			
			/**  フォント関連 
			 *ここでいうフォントは、OSが持つものではなく、独自にビットマップで保持しているものをさします。*/
			namespace font {
				const int COUNT_MAX = 2;///< フォントの数
				const int TEXTURE_WIDTH = 128;///< フォントビットマップの幅
				const int TEXTURE_HEIGHT = 64;///< フォントビットマップの高さ
				const int WIDTH = 8;///< フォントの幅
				const int HEIGHT = 8;///< フォントの高さ
				/// フォントファイルネーム配列 
				const char FILE_PATH[COUNT_MAX][MAX_PATH_] 
					= {	"media\\font1.png",
					"media\\font2.png"
				};
			}

			/// テキスト制御関連
			namespace text {
				const int BUFFER_LENGTH = 1024;///< テキスト保持バッファのサイズ
				const float COLUMN_PITCH = 8.0f;///< テキストのカラムピッチ
				const float LINE_PITCH = 10.0f;///< テキストの行ピッチ
			}

			/// カスタム頂点フォーマット
			struct Vertex {
				float		x,///< x座標
							y,///< y座標
							z,///< z座標
							rhw;///< ???
				DWORD	diffuse,///< ディフューズ成分
						specular;///< スペキュラー成分
				float   tu,///< テクスチャのu成分
						tv;///< テクスチャのv成分
			};


			/// 画面の描画制御を行う
			/*! 画面の描画制御を行うインターフェースです。 
			 * @note Consoleクラスは、OS固有の画面描画周りの実装を抽象化する目的があります。<br>抽象化を行う際には、OSに依存しないより一般化した言葉で記述すべきですが、
			 * 作者がDirectXしか知らないため、実装および解説にOS固有の表現がある可能性があります。*/
			class Console 
			{
				// LIFECYCLE //
			public:
				/// デストラクタ
				virtual ~Console(){;};

				// OPERATORS //
				// OPERATIONS //
				/** Consoleインターフェースの初期化を行う 
				 * Console インターフェースの実装クラスの初期化を行うための仮想関数で、通常アプリケーションから呼び出されることはありません。
				 */
				virtual void initialize(void) = 0;

				/** 画面消去を行う.
				 * スクリーンを消去します。
				 * @param value 塗りつぶす色 */
				virtual void clearScreen(COLOR value = 0x00000000) = 0;

				/** 画面消去を行う.
				 * スクリーンを指定色で塗りつぶします。
				 * @param value 塗りつぶす色 */
				virtual void fillScreen(COLOR value = 0x00000000) = 0;

				/** 画面更新を行う. 
				 * 画面更新を行います。
				 * Windowsでは、バックバッファからプライマリサーフェースへの転送を行います。
				 * また、スプライトの描画、テキストバッファに蓄積された文字列の描画もあわせて行います。
				 */
				virtual void update(void) = 0;
				
				/// バックバッファにAscii文字列を指定したテクスチャー番号で表示する。
				/*! @param textureNo フォント用テクスチャの番号 @ref sf::system::console::font::FILE_PATH を参照
				 *	@param x 表示開始X座標
				 *	@param y 表示開始Y座標
				 *	@param angleRad 表示角度をラジアンで指定
				 *	@param scale 拡大縮小率
				 *	@param color 表示色
				 *  @param format printfのフォーマット文字列
				 *  @param ... 表示したい変数列 */  
				virtual void print(const int textureNo,const float x,const float y,const float angleRad,const float scale,const COLOR color,
					const char *format,...) = 0;

				/**  スプライトデータをロードする. 
				 * sprite::Infoの情報に従ってスプライトデータをロードし、Spriteインターフェースのポインタを返します。
				 * @param pInfo sprite::Info 構造体のポインタ 
				 * @return Spriteインターフェースへのポインタ */
				virtual sprite::Sprite * const createSprite(const sprite::Info* const pInfo) = 0;
				// ACCESS //
				
				// INQUIRY //
				/// コンソールが使用可か否かを返す
				/*! @retval true 使用可 
				 *  @retval false 使用不可 */
				virtual const bool isEnabled(void) const = 0;
			};// Console()
			
			/** スプライト描画タイプ 
			 *
			 * スプライトの透過処理をどのタイプで行うか指定します。 */
			enum DrawMode {
				DRAW_TRANS,///< 通常の透過処理
				DRAW_ADD,///< 加算合成
				DRAW_ADD1,///< 加算合成1
				DRAW_SHADOW,///< 忘れました
				DRAW_INV,///< 反転合成
				DRAW_MUL///< 乗算合成
			};// DrawMode

		}// namespace console
	}// namespace system
}//namespace sf
}
#endif // !defined(AFX_IConsole_H__DB7BCF98_4A51_43E3_B919_9A26C58E6A90__INCLUDED_)
