/*!
* @file GameSurfaceSDL.h
* @brief GameSurfaceSDLクラスとその他付随要素のプロトタイプ
* @date 2014/02/19
* @author Deskull
* 2014 Sikabane Works.
*/

#pragma once

#include "stdafx.h"

#include <SDL.h>
#include <SDL_image.h>
//#include <SDL_gfx.h>
#include <SDL_ttf.h>

#include "GameSurface.h"


namespace Deeangband
{
	class Creature;

	#define FPS_UPDATE 20 //!< FPS計算を更新するフレーム数
	#define WAIT_MSEC 16 //!< ウェイトミリ秒(FPS = 1000.0 / WAIT_MSEC)

	struct SDL_Rect_Dee : public SDL_Rect
	{
		SDL_Rect_Dee(int x, int y, int w, int h)
		{
			this->x = x;
			this->y = y;
			this->w = w;
			this->h = h;
		}

		void SDL_Rect_Dee::Set(int x, int y, int w, int h)
		{
			this->x = x;
			this->y = y;
			this->w = w;
			this->h = h;
		}

		SDL_Rect_Dee SDL_Rect_Dee::operator+(const SDL_Rect_Dee& plus)
		{
			this->x += plus.x;
			this->y += plus.y;
			return *this;
		}

		SDL_Rect_Dee()
		{
			this->x = 0;
			this->y = 0;
			this->w = 0;
			this->h = 0;
		}
	};

	/*! 
	 * @class GameSurfaceSDL
	 * @brief ゲームのメインインターフェイスクラス(SDL実装)
	 */
	class GameSurfaceSDL : public GameSurface
	{
	private:

		static const int squareGraphicWidth = 24; //!< 1マスのグラフィック幅(ピクセル) 
		static const int squareGraphicHeight = 24; //!< 1マスのグラフィック高さ(ピクセル) 
		static const int fieldPadding = 3; //!< 隅表示時の最大隙間(スクエア) 

		SDL_Rect_Dee rectTitleDst; //!< タイトルグラフィック転送先座標
		SDL_Rect_Dee rectTitleSrc; //!< タイトルグラフィック転送元座標

		SDL_Rect_Dee rectFpsDst; //!< FPS表示転送先座標
		SDL_Rect_Dee rectFpsSrc; //!< FPS表示転送元座標

		SDL_Rect_Dee rectMainMapDst; //!< メインマップ表示転送先

		SDL_Renderer *renderer;     //!< SDL用レンダラ参照ポインタ
		SDL_Window *window;         //!< SDLウィンドウ参照ポインタ

		Creature *viewCreaturePtr;       //!< 現在のステータス表示対象となるCreature参照ポインタ
		Creature *sideStatusCreatutePtr; //!< 現在のステータス簡易表示対象となるCreature参照ポインタ
		Field *viewFieldPtr;       //!< 描画対象となるField参照
		Coordinates focusPoint;    //!< フロアの描画左上地点

		TTF_Font* font;  //!< 描画標準フォントポインタ
		TTF_Font* fontSmall;  //!< 描画小型フォントポインタ
		SDL_Color color; //!< カラー標準ポインタ

		SDL_RWops *rwop;
		std::string currentGameMessage; //!< 現在表示中のゲームメッセージstring
		std::string currentSystemMessage; //!< 現在表示中のシステムメッセージstring
		std::string error;
		SDL_Rect src;
		SDL_Rect title;

		SDL_Surface *windowSurface;  //!< ゲームウィンドウのSurface参照

		SDL_Texture *titleTexture;   //!< ゲームタイトルグラフィックのTexture参照
		SDL_Texture *unknownFieldTexture; //!< 未知フィールドグラフィックのTexture参照
		SDL_Texture *unseenFieldTexture; //!< 視界外フィールドグラフィックのTexture参照

		SDL_Texture *systemMessageTexture; //!< システムメッセージグラフィックのSurface参照
		SDL_Texture *gameMessageTexture; //!< ゲームメッセージグラフィックのSurface参照
		SDL_Texture *creatureStatusTexture;  //!< クリーチャーステータス表示のSurface参照
		SDL_Texture *creatureSideStatusTexture;  //!< サイドクリーチャーステータス表示のSurface参照
		SDL_Texture *gameTimeStatusTexture;  //!< ゲーム時間表示のSurface参照
		SDL_Texture *fpsTexture;


		std::map<TAG, SDL_Texture*> floorTextures; //!< フロアグラフィックのSurface参照リスト
		std::map<ID, SDL_Texture*> creatureTextures; //!< クリーチャーグラフィックのSurface参照リスト

		void GameSurfaceSDL::pushAnyKey(const CREATURE_IT &subjectCreatureIt);
		void GameSurfaceSDL::pushAnyKey(void);

        int frameDeltaTime;
        int frameTime;
        int frameCount;
        int framesPerSecond;
        int frameTimeLast;
        int frameDeltaTimeLast;

		/*!
		 * @brief インターフェイスデータの初期化
		 * @param gameWorld インターフェイスを初期化する際に必要な情報を得るためのGameWorld参照
		 * @return なし
		 */
		void GameSurfaceSDL::initInterfaces(GameWorld *gameWorld);

		void GameSurfaceSDL::drawCreatureStatus(Creature *creaturePtr);

		/*!
		 * @brief フロアを描画する
		 * @param fieldPtr 表示したいフロアの構造体参照ポインタ
		 * @param gameWorld GameWorld参照ポインタ
		 * @param rectDraw 描画域
		 * @param x 左上起点のX座標
		 * @param y 左上起点のY座標
		 * @param w 表示のマス幅
		 * @param h 表示のマス高さ
		 * @return なし
		 */
		void GameSurfaceSDL::drawField(const CREATURE_IT &subjectCreatureIt, GameWorld *gameWorld, Field *fieldPtr, SDL_Rect_Dee &rectDraw);

		/*!
		 * @brief サイドステータスを描画する
		 * @return なし
		 */
		void GameSurfaceSDL::drawSideCreatureStatus(void);

		/*!
		 * @brief システムメッセージを描画する
		 * @return なし
		 */
		void GameSurfaceSDL::drawSystemMessage(void);

		/*!
		 * @brief ゲームメッセージを描画する
		 * @return なし
		 */
		void GameSurfaceSDL::drawGameMessage(void);

		/*!
		 * @brief ゲーム時間情報を描画する
		 * @return なし
		 */
		void GameSurfaceSDL::drawTimeStatus(void);

		void GameSurfaceSDL::fpsProcess(void);


	public:

		/*!
		 * @brief ゲーム画面を再描画する
		 * @param subjectCreatureIt 主観となるクリーチャーイテレータ
		 * @return なし
		 */
		void GameSurfaceSDL::Draw(const CREATURE_IT& subjectCreatureIt);

		/*!
		 * @brief ゲーム時間表示を更新する
		 * @param currentTime 現在時刻
		 * @return なし
		 */
		void GameSurfaceSDL::UpdateTimeStatus(GAME_TIME currentTime);

		/*!
		 * @brief サイドステータス表示を更新する
		 * @param creaturePtr 更新元クリーチャー参照ポインタ
		 * @return なし
		 */
		void GameSurfaceSDL::UpdateSideCreatureStatus(Creature *creaturePtr);


		/*!
		 * @brief 指定されたクリーチャーのステータスを表示する
		 * @param creaturePtr 表示したいクリーチャーの参照ポインタ
		 * @return なし
		 */
		void GameSurfaceSDL::ViewCreatureStatus(Creature *creaturePtr);

		/*!
		 * @brief ゲーム画面左にプレイヤー簡略情報を表示する。
		 * @param creaturePtr 表示したいクリーチャーのインスタンス参照ポインタ。NULLならば非表示。
		 * @return なし
		 */
		void GameSurfaceSDL::SetSideStatusCreature(Creature *creaturePtr);

		/*!
		 * @brief 表示するフロアを切り替える
		 * @param fieldPtr 表示したいフロアの参照ポインタ
		 * @return なし
		 */
		void GameSurfaceSDL::SetField(Field *fieldPtr);

		/*!
		 * @brief コンストラクタ
		 * @param gameWorld 処理したいGameWorldインスタンス
		 */
		GameSurfaceSDL::GameSurfaceSDL(GameWorld *gameWorld);

		/*!
		 * @brief デストラクタ
		 */
		GameSurfaceSDL::~GameSurfaceSDL(void);

		/*!
		 * @brief プレイヤーからコマンドを取得する
		 * @return ゲームコマンドID
		 */
		GAME_COMMAND GameSurfaceSDL::GetCommand(const CREATURE_IT& subjectCreatureIt);

		/*!
		 * @brief フロア表示のフォーカスを変更する
		 * @param x 基準X座標
		 * @param y 基準Y座標
		 * @return なし
		 */
		void GameSurfaceSDL::FocusField(MAP_LENGTH x, MAP_LENGTH y);

		/*!
		* @brief フロア表示のフォーカスを変更する
		* @param coord 基準座標
		* @return なし
		*/
		void GameSurfaceSDL::FocusField(Coordinates coord);

		/*!
		 * @brief システムメッセージを表示する
		 * @param message メッセージ
		 * @return なし
		 */
		void GameSurfaceSDL::SystemMessage(std::string message);

		/*!
		 * @brief ゲームメッセージを表示する
		 * @param message メッセージ
		 * @return なし
		 */
		void GameSurfaceSDL::GameMessage(std::string message);

		/*!
		 * @brief クリーチャー用グラフィックを新規作成/更新する
		 * @param message メッセージ
		 * @return なし
		 */
		void GameSurfaceSDL::updateCreatureGraphics(CREATURE_IT creatureIt);


	};

}