/*!
* @file GameSurfaceSDL.cpp
* @brief ゲームのメインインターフェイス(SDL2.0実装)
* @date 2014/02/19
* @author Deskull
* 2014 Sikabane Works.
*/

#include <vector>
#include <string>
#include "stdafx.h"
#include "GameSurfaceSDL.h"

#include "GameEngine.h"

#include "Creature.h"
#include "Field.h"

namespace Deeangband
{

	std::string toUTF8(LPCSTR str)
	{
		const int cchWideChar = ::MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
		std::vector<WCHAR> lpw(cchWideChar);

		const int nUnicodeCount = ::MultiByteToWideChar(CP_ACP, 0, str, -1, &lpw[0], cchWideChar);
		if(nUnicodeCount <= 0)
		{
			return "";
		}

		const int cchMultiByte = ::WideCharToMultiByte(CP_UTF8, 0, &lpw[0], -1, NULL, 0, NULL, NULL);
		std::vector<CHAR> lpa(cchMultiByte);

		const int nMultiCount = ::WideCharToMultiByte(CP_UTF8, 0, &lpw[0], -1, &lpa[0], cchMultiByte, NULL, NULL);
		if(nMultiCount <= 0)
		{
			return "";
		}
		return std::string(&lpa[0]);
	}

	GameSurfaceSDL::GameSurfaceSDL(GameWorld *gameWorld) : GameSurface(gameWorld)
	{
		if(SDL_Init(SDL_INIT_VIDEO) < 0) return;
		window = SDL_CreateWindow(GAME_TITLE, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, WINDOW_WIDTH, WINDOW_HEIGHT, SDL_WINDOW_RESIZABLE);
		SDL_GetWindowSurface(window);
		renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
		if(!window) return;

		if(TTF_Init() == -1) return;
		if(IMG_Init(IMG_INIT_PNG) != IMG_INIT_PNG) return;

		initInterfaces(gameWorld);

		viewCreaturePtr = NULL;
		viewFieldPtr = NULL;

		windowSurface = SDL_GetWindowSurface(window);

		gameMessageTexture = NULL;
		systemMessageTexture = NULL;

		frameTime = 0;
		frameCount = 0;
		framesPerSecond = 0;
		frameDeltaTimeLast = frameTimeLast = SDL_GetTicks();

		SDL_SetRenderDrawBlendMode(this->renderer, SDL_BLENDMODE_NONE);

		this->rectTitleDst.Set(10, 10, 266, 266);
		this->rectTitleSrc.Set(0, 0, 256, 256);
		this->rectFpsDst.Set(0, 0, 50, 20);
		this->rectFpsSrc.Set(0, 0, 50, 20);

		return;
	}

	GameSurfaceSDL::~GameSurfaceSDL(void)
	{
		IMG_Quit();
		TTF_Quit();
		SDL_Quit();
		return;
	}

	void GameSurfaceSDL::fpsProcess()
	{
		SDL_Surface *surface;
		char fpsBuf[12];
        int getTicks;

		frameCount++;
		getTicks = SDL_GetTicks();
		frameDeltaTime = getTicks - frameDeltaTimeLast;
		frameDeltaTimeLast = getTicks;
        if (frameCount >= FPS_UPDATE)
		{
			frameCount = 0;
			frameTime = getTicks - frameTimeLast;
			frameTimeLast = getTicks;
			framesPerSecond = (int)(1000.f * FPS_UPDATE / frameTime);
			sprintf_s(fpsBuf, 8, "fps:%d", framesPerSecond); 
			surface = TTF_RenderUTF8_Blended(fontSmall, fpsBuf, color);
			fpsTexture = SDL_CreateTextureFromSurface(renderer, surface);
			SDL_FreeSurface(surface);
		}

		SDL_RenderCopy(renderer, fpsTexture, &rectFpsSrc, &rectFpsDst); 

	}

	void GameSurfaceSDL::pushAnyKey(const CREATURE_IT& subjectCreatureIt)
	{
		SDL_Event event;
		do 
		{
			SDL_PollEvent(&event);
		} while(event.type != SDL_KEYDOWN);
	}

	void GameSurfaceSDL::pushAnyKey(void)
	{
		SDL_Event event;
		do 
		{
			SDL_Rect rect = {0, 0, 0, 0};
			this->drawSystemMessage();
			SDL_UpdateWindowSurfaceRects(window, &rect, 1);
			SDL_UpdateWindowSurface(window);

			SDL_PollEvent(&event);
		} while(event.type != SDL_KEYDOWN);
	}


	void GameSurfaceSDL::initInterfaces(GameWorld *gameWorld)
	{
		std::map<TAG, std::shared_ptr<Floor>>::iterator floorIt;
		std::map<TAG, std::shared_ptr<Species>>::iterator speciesIt;
		SDL_Surface *surface, *tempSurface, *symbolSurface;

		//! @note TTFフォントの読み込み

		font = TTF_OpenFont("ttf\\ipam.ttf", 14);
		fontSmall = TTF_OpenFont("ttf\\ipag.ttf", 9);
		src.x = 0;
		src.y = 0;
		src.w = 300;
		src.h = 200;
		title.x = 0;
		title.y = 0;
		title.w = 256;
		title.h = 256;
		color.r = 255;
		color.g = 223;
		color.b = 200;
		color.a = 255;

		if(!font || !fontSmall)
		{	
			OutputDebugString(L"Failed: loading .ttf files.\n");
			exit(1);
		}

		//! @note システムグラフィックの読み込み
		rwop = SDL_RWFromFile("img\\Title.png", "rb");
		error = IMG_GetError();
		tempSurface = IMG_LoadPNG_RW(rwop);
		titleTexture = SDL_CreateTextureFromSurface(renderer, tempSurface);
		SDL_FreeSurface(tempSurface);

		//! @note 未知地形グラフィックの読み込み
		rwop = SDL_RWFromFile("img\\UnknownField.png", "rb");
		error = IMG_GetError();
		tempSurface = IMG_LoadPNG_RW(rwop);
		unknownFieldTexture = SDL_CreateTextureFromSurface(renderer, tempSurface);
		SDL_FreeSurface(tempSurface);

		//! @note 視界外地形グラフィックの読み込み
		rwop = SDL_RWFromFile("img\\UnseenField.png", "rb");
		error = IMG_GetError();
		tempSurface = IMG_LoadPNG_RW(rwop);
		unseenFieldTexture = SDL_CreateTextureFromSurface(renderer, tempSurface);
		SDL_FreeSurface(tempSurface);

		//! @note 床地形グラフィックの設定
		for(floorIt = gameWorld->GetFloorList()->begin(); floorIt != gameWorld->GetFloorList()->end(); floorIt++)
		{
			Color symColor = floorIt->second->GetSymbolColor();
			Color backColor = floorIt->second->GetBackColor();
			SDL_Color sdlSymCol = {(Uint8)symColor.GetRed(), (Uint8)symColor.GetGreen(), (Uint8)symColor.GetBlue(), (Uint8)symColor.GetAlpha()};
			SDL_Rect blitRect = {0, 0, squareGraphicWidth, squareGraphicHeight};
			SDL_Rect symbolRect = {0, 0, 30, 30};
			char symBuf[80];

			surface = SDL_CreateRGBSurface(0, squareGraphicWidth, squareGraphicHeight, 32, 0, 0, 0, 0);

			SDL_FillRect(surface, &blitRect, SDL_MapRGBA(surface->format, (Uint8)backColor.GetRed(), (Uint8)backColor.GetGreen(), (Uint8)backColor.GetBlue(), (Uint8)backColor.GetAlpha()));
			sprintf_s(symBuf, 5, "%s", floorIt->second->GetSymbol().c_str()); 
			symbolSurface = TTF_RenderUTF8_Blended(font, toUTF8(symBuf).c_str(), sdlSymCol);
			blitRect.x += (24 - symbolSurface->w) / 2;
			blitRect.y += (24 - symbolSurface->h) / 2;
			SDL_BlitSurface(symbolSurface, &symbolRect, surface, &blitRect);
			SDL_FreeSurface(symbolSurface);

			floorTextures.insert(std::map<TAG, SDL_Texture*>::value_type(floorIt->first, SDL_CreateTextureFromSurface(renderer, surface)));
		}

		SDL_GetWindowSurface(this->window);
		this->windowSurface = SDL_GetWindowSurface(this->window);
	}

	void GameSurfaceSDL::Draw(const CREATURE_IT& subjectCreatureIt)
	{
		SDL_Rect rectTemp = {0, 0, 0, 0};

		SDL_RenderClear(renderer);
		SDL_GetWindowSize(window, &rectTemp.w, &rectTemp.h);

		SDL_RenderCopy(renderer, titleTexture, &rectTitleSrc, &rectTitleDst); 

		this->rectMainMapDst.Set(240, 30, rectTemp.w - 260, rectTemp.h - 60);
		SDL_SetRenderDrawColor(renderer, 50, 20, 0, 255);

		if(this->viewFieldPtr)
		{
			this->drawField(subjectCreatureIt, gameWorld, viewFieldPtr, rectMainMapDst);
		}
		if(this->sideStatusCreatutePtr) this->drawSideCreatureStatus();
		if(this->viewCreaturePtr) this->drawCreatureStatus(viewCreaturePtr);
		if(this->currentSystemMessage.size() > 0) this->drawSystemMessage();
		if(this->gameMessageTexture) this->drawGameMessage();
		this->drawTimeStatus();

		this->fpsProcess();
		SDL_Delay(WAIT_MSEC - frameDeltaTime > 0 ? WAIT_MSEC - frameDeltaTime : 0);

		SDL_RenderPresent(renderer);

		return;
	}

	void GameSurfaceSDL::ViewCreatureStatus(Creature *creaturePtr)
	{
		this->viewCreaturePtr = creaturePtr;
		//pushAnyKey(NULL);
		this->viewCreaturePtr = NULL;
	}

	void GameSurfaceSDL::SetSideStatusCreature(Creature *creaturePtr)
	{
		this->sideStatusCreatutePtr = creaturePtr;
		if(creaturePtr) this->UpdateSideCreatureStatus(creaturePtr);
	}

	void GameSurfaceSDL::SetField(Field *fieldPtr)
	{
		this->viewFieldPtr = fieldPtr;
	}

	void GameSurfaceSDL::drawCreatureStatus(Creature *creaturePtr)
	{
		int id;

		enum CREATURE_STATUS_VIEW_POSITION
		{
			POS_NAME,
			POS_LEVEL,
			POS_HP,
			POS_MP,
			POS_AC,
			POS_EV,
			POS_VO,
			POS_STR,
			POS_INT,
			POS_WIS,
			POS_DEX,
			POS_CON,
			POS_CHA,
			POS_SOUL,
			POS_GOOD,
			POS_EVIL,
			POS_ORDER,
			POS_CHAOS,
			POS_BALANCE,
			POS_HEIGHT,
			POS_WEIGHT,
			POS_BODY_SIZE,
			POS_MAX
		};

		SDL_Rect CreatureStatusViewPosition[POS_MAX] =
		{
			{10, 10, 0, 0},
			{10, 30, 0, 0},
			{10, 50, 0, 0},
			{10, 70, 0, 0},
			{10, 90, 0, 0},
			{10, 110, 0, 0},
			{10, 130, 0, 0},
			{200, 30, 0, 0},
			{200, 50, 0, 0},
			{200, 70, 0, 0},
			{200, 90, 0, 0},
			{200, 110, 0, 0},
			{200, 130, 0, 0},
			{200, 150, 0, 0},
			{200, 170, 0, 0},
			{200, 190, 0, 0},
			{200, 210, 0, 0},
			{200, 230, 0, 0},
			{200, 250, 0, 0},
			{10, 150, 0, 0},
			{10, 170, 0, 0},
			{10, 190, 0, 0},
		};

		SDL_Rect CreatureStatusViewRect[POS_MAX];

		const int STATUS_BUFSIZE = 100;
		char statusBuf[POS_MAX][STATUS_BUFSIZE];
		SDL_Surface *statusSurface[POS_MAX];

		SDL_Rect masterRect = {10, 10, 490, 450};

		sprintf_s(statusBuf[POS_NAME], STATUS_BUFSIZE, "名前:%s", creaturePtr->GetName().c_str()); 
		sprintf_s(statusBuf[POS_LEVEL], STATUS_BUFSIZE, "LV:%3d", creaturePtr->GetLevel()); 
		sprintf_s(statusBuf[POS_HP], STATUS_BUFSIZE, "HP:%5d/%5d", creaturePtr->GetCurHP(), creaturePtr->GetMaxHP()); 
		sprintf_s(statusBuf[POS_MP], STATUS_BUFSIZE, "MP:%5d/%5d", creaturePtr->GetCurMP(), creaturePtr->GetMaxMP()); 
		sprintf_s(statusBuf[POS_AC], STATUS_BUFSIZE, "AC:%4d", creaturePtr->GetArmorSaving()); 
		sprintf_s(statusBuf[POS_EV], STATUS_BUFSIZE, "EV:%4d", creaturePtr->GetEvasionSaving()); 
		sprintf_s(statusBuf[POS_VO], STATUS_BUFSIZE, "VO:%4d", creaturePtr->GetVolitionSaving()); 
		sprintf_s(statusBuf[POS_GOOD], STATUS_BUFSIZE, " 善 :%4d", creaturePtr->GetDiscipilneRank(DISCIPLINE_TYPE_GOOD)); 
		sprintf_s(statusBuf[POS_EVIL], STATUS_BUFSIZE, " 悪 :%4d", creaturePtr->GetDiscipilneRank(DISCIPLINE_TYPE_EVIL)); 
		sprintf_s(statusBuf[POS_ORDER], STATUS_BUFSIZE, "秩序:%4d", creaturePtr->GetDiscipilneRank(DISCIPLINE_TYPE_ORDER)); 
		sprintf_s(statusBuf[POS_CHAOS], STATUS_BUFSIZE, "混沌:%4d", creaturePtr->GetDiscipilneRank(DISCIPLINE_TYPE_CHAOS)); 
		sprintf_s(statusBuf[POS_BALANCE], STATUS_BUFSIZE, "天秤:%4d", creaturePtr->GetDiscipilneRank(DISCIPLINE_TYPE_BALANCE)); 
		sprintf_s(statusBuf[POS_STR], STATUS_BUFSIZE, "腕力:%4d", creaturePtr->GetCurrentStatus(CS_STR)); 
		sprintf_s(statusBuf[POS_INT], STATUS_BUFSIZE, "知力:%4d", creaturePtr->GetCurrentStatus(CS_INT)); 
		sprintf_s(statusBuf[POS_WIS], STATUS_BUFSIZE, "賢さ:%4d", creaturePtr->GetCurrentStatus(CS_WIS)); 
		sprintf_s(statusBuf[POS_DEX], STATUS_BUFSIZE, "器用:%4d", creaturePtr->GetCurrentStatus(CS_DEX)); 
		sprintf_s(statusBuf[POS_CON], STATUS_BUFSIZE, "耐久:%4d", creaturePtr->GetCurrentStatus(CS_CON)); 
		sprintf_s(statusBuf[POS_CHA], STATUS_BUFSIZE, "魅力:%4d", creaturePtr->GetCurrentStatus(CS_CHA)); 
		sprintf_s(statusBuf[POS_SOUL], STATUS_BUFSIZE, "ソウル:%4d", creaturePtr->GetCurrentSoul()); 
		sprintf_s(statusBuf[POS_HEIGHT], STATUS_BUFSIZE, "身長:%13s", GameElement::HeightFormat(creaturePtr->GetHeight()).c_str()); 
		sprintf_s(statusBuf[POS_WEIGHT], STATUS_BUFSIZE, "体重:%13s", GameElement::WeightFormat(creaturePtr->GetWeight()).c_str()); 
		sprintf_s(statusBuf[POS_BODY_SIZE], STATUS_BUFSIZE, "体格:%3d", creaturePtr->GetSize()); 

		for(id = 0; id < POS_MAX; id++)
		{
			statusSurface[id] = TTF_RenderUTF8_Blended(font, toUTF8(statusBuf[id]).c_str(), color);
			CreatureStatusViewRect[id].x = 0;
			CreatureStatusViewRect[id].y = 0;
			CreatureStatusViewRect[id].w = statusSurface[id]->w;
			CreatureStatusViewRect[id].h = statusSurface[id]->h;
			CreatureStatusViewPosition[id].x += masterRect.x;
			CreatureStatusViewPosition[id].y += masterRect.y;
		}

		SDL_FillRect(windowSurface, &masterRect, SDL_MapRGBA(windowSurface->format, 0, 0, 0, 120));

		for(id = 0; id < POS_MAX; id++)
		{
			SDL_BlitSurface(statusSurface[id], &CreatureStatusViewRect[id], windowSurface, &CreatureStatusViewPosition[id]); 
		}

		for(id = 0; id < POS_MAX; id++)
		{
			SDL_FreeSurface(statusSurface[id]);
		}
		return;
	}

	void GameSurfaceSDL::UpdateTimeStatus(GAME_TIME currentTime)
	{

		SDL_Rect rect = {0, 0, 200, 50};
		SDL_Rect StatusViewRect = {0, 0, 200, 50};
		SDL_Rect StatusViewPosition = {10, 10, 0, 0};
		SDL_Surface *surface, *statusSurface;
		const int STATUS_BUFSIZE = 100;
		char statusBuf[STATUS_BUFSIZE];
		if(gameTimeStatusTexture) SDL_DestroyTexture(gameTimeStatusTexture);
		surface = SDL_CreateRGBSurface(0, 200, 50, 32, 0, 0, 0, 0);
		SDL_FillRect(surface, &rect, SDL_MapRGBA(windowSurface->format, 0, 0, 0, 120));
		sprintf_s(statusBuf, STATUS_BUFSIZE, "ゲーム時間:%d", currentTime); 
		statusSurface = TTF_RenderUTF8_Blended(font, toUTF8(statusBuf).c_str(), color);
		SDL_BlitSurface(statusSurface, &StatusViewRect, surface, &StatusViewPosition); 
		gameTimeStatusTexture = SDL_CreateTextureFromSurface(renderer, surface);
		SDL_FreeSurface(statusSurface);
		SDL_FreeSurface(surface);
	}

	void GameSurfaceSDL::UpdateSideCreatureStatus(Creature *creaturePtr)
	{
		int id;
		SDL_Surface *surface;

		enum CREATURE_SIDE_STATUS_VIEW_POSITION
		{
			POS_NAME,
			POS_LEVEL,
			POS_HP,
			POS_MP,
			POS_AC,
			POS_EV,
			POS_VO,
			POS_STR,
			POS_INT,
			POS_WIS,
			POS_DEX,
			POS_CON,
			POS_CHA,
			POS_SOUL,
			POS_X,
			POS_Y,
			POS_MAX
		};

		SDL_Rect CreatureStatusViewPosition[POS_MAX] =
		{
			{10, 10, 0, 0},
			{10, 30, 0, 0},
			{10, 50, 0, 0},
			{10, 70, 0, 0},
			{10, 90, 0, 0},
			{10, 110, 0, 0},
			{10, 130, 0, 0},
			{200, 30, 0, 0},
			{200, 50, 0, 0},
			{200, 70, 0, 0},
			{200, 90, 0, 0},
			{200, 110, 0, 0},
			{200, 130, 0, 0},
			{200, 150, 0, 0},
			{10, 170, 0, 0},
			{70, 170, 0, 0},
		};

		SDL_Rect CreatureStatusViewRect[POS_MAX];

		const int STATUS_BUFSIZE = 100;
		char statusBuf[POS_MAX][STATUS_BUFSIZE];
		SDL_Surface *statusSurface[POS_MAX];
		
		SDL_Rect masterRect = {0, 0, 180, 350};

		surface = SDL_CreateRGBSurface(0, 180, 350, 32, 0, 0, 0, 0);

		sprintf_s(statusBuf[POS_NAME], STATUS_BUFSIZE, "名前:%s", creaturePtr->GetName().c_str()); 
		sprintf_s(statusBuf[POS_LEVEL], STATUS_BUFSIZE, "LV:%3d", creaturePtr->GetLevel()); 
		sprintf_s(statusBuf[POS_HP], STATUS_BUFSIZE, "HP:%5d/%5d", creaturePtr->GetCurHP(), creaturePtr->GetMaxHP()); 
		sprintf_s(statusBuf[POS_MP], STATUS_BUFSIZE, "MP:%5d/%5d", creaturePtr->GetCurMP(), creaturePtr->GetMaxMP()); 
		sprintf_s(statusBuf[POS_AC], STATUS_BUFSIZE, "AC:%4d", creaturePtr->GetArmorSaving()); 
		sprintf_s(statusBuf[POS_EV], STATUS_BUFSIZE, "EV:%4d", creaturePtr->GetEvasionSaving()); 
		sprintf_s(statusBuf[POS_VO], STATUS_BUFSIZE, "VO:%4d", creaturePtr->GetVolitionSaving()); 
		sprintf_s(statusBuf[POS_STR], STATUS_BUFSIZE, "腕力:%4d", creaturePtr->GetCurrentStatus(CS_STR)); 
		sprintf_s(statusBuf[POS_INT], STATUS_BUFSIZE, "知力:%4d", creaturePtr->GetCurrentStatus(CS_INT)); 
		sprintf_s(statusBuf[POS_WIS], STATUS_BUFSIZE, "賢さ:%4d", creaturePtr->GetCurrentStatus(CS_WIS)); 
		sprintf_s(statusBuf[POS_DEX], STATUS_BUFSIZE, "器用:%4d", creaturePtr->GetCurrentStatus(CS_DEX)); 
		sprintf_s(statusBuf[POS_CON], STATUS_BUFSIZE, "耐久:%4d", creaturePtr->GetCurrentStatus(CS_CON)); 
		sprintf_s(statusBuf[POS_CHA], STATUS_BUFSIZE, "魅力:%4d", creaturePtr->GetCurrentStatus(CS_CHA)); 
		sprintf_s(statusBuf[POS_SOUL], STATUS_BUFSIZE, "ソウル:%4d", creaturePtr->GetCurrentSoul()); 
		sprintf_s(statusBuf[POS_X], STATUS_BUFSIZE, "X:%4d", creaturePtr->GetPosition().GetX()); 
		sprintf_s(statusBuf[POS_Y], STATUS_BUFSIZE, "Y:%4d", creaturePtr->GetPosition().GetY()); 

		for(id = 0; id < POS_MAX; id++)
		{
			statusSurface[id] = TTF_RenderUTF8_Blended(font, toUTF8(statusBuf[id]).c_str(), color);
			CreatureStatusViewRect[id].x = 0;
			CreatureStatusViewRect[id].y = 0;
			CreatureStatusViewRect[id].w = statusSurface[id]->w;
			CreatureStatusViewRect[id].h = statusSurface[id]->h;
			CreatureStatusViewPosition[id].x += masterRect.x;
			CreatureStatusViewPosition[id].y += masterRect.y;
		}

		SDL_FillRect(surface, &masterRect, SDL_MapRGBA(surface->format, 0, 0, 0, 120));

		for(id = 0; id < POS_MAX; id++)
		{
			SDL_BlitSurface(statusSurface[id], &CreatureStatusViewRect[id], surface, &CreatureStatusViewPosition[id]); 
		}

		for(id = 0; id < POS_MAX; id++)
		{
			SDL_FreeSurface(statusSurface[id]);
		}

		creatureSideStatusTexture = SDL_CreateTextureFromSurface(renderer, surface);
		SDL_FreeSurface(surface);

		return;

	}

	void GameSurfaceSDL::drawSideCreatureStatus(void)
	{
		SDL_Rect masterRect = {0, 0, 180, 350};
		SDL_Rect posRect = {10, 120, 180, 350};
		SDL_RenderCopy(renderer, creatureSideStatusTexture, &masterRect, &posRect);
	}

	GAME_COMMAND GameSurfaceSDL::GetCommand(const CREATURE_IT& subjectCreatureIt)
	{
		SDL_Event event;
		SDL_Keycode key;

		while (SDL_PollEvent(&event))
		{
			Sleep(10);
			switch(event.type)
			{

			case SDL_KEYDOWN:
				{
					key=event.key.keysym.sym;

					switch(key)
					{
					case SDLK_ESCAPE:
						return GAME_COMMAND_EXIT;
					case SDLK_c:
						return GAME_COMMAND_VIEW_PLAYER_STATUS;
					case SDLK_F11:
						return GAME_COMMAND_DEBUG_XML_SAVE;
					case SDLK_F12:
						return GAME_COMMAND_DEBUG_XML_LOAD;
					case SDLK_k:
						return GAME_COMMAND_NORTH;
					case SDLK_u:
						return GAME_COMMAND_NORTH_EAST;
					case SDLK_l:
						return GAME_COMMAND_EAST;
					case SDLK_n:
						return GAME_COMMAND_SOUTH_EAST;
					case SDLK_j:
						return GAME_COMMAND_SOUTH;
					case SDLK_b:
						return GAME_COMMAND_SOUTH_WEST;
					case SDLK_h:
						return GAME_COMMAND_WEST;
					case SDLK_y:
						return GAME_COMMAND_NORTH_WEST;
					case SDLK_s:
						return GAME_COMMAND_STAY;
					}

				}
				break;

			case SDL_WINDOWEVENT:
				switch (event.window.event) {
				case SDL_WINDOWEVENT_SHOWN:
					break;
				case SDL_WINDOWEVENT_HIDDEN:
					break;
				case SDL_WINDOWEVENT_EXPOSED:
					break;
				case SDL_WINDOWEVENT_MOVED:
					break;
				case SDL_WINDOWEVENT_RESIZED:
					break;
				case SDL_WINDOWEVENT_MINIMIZED:
					break;
				case SDL_WINDOWEVENT_MAXIMIZED:
					break;
				case SDL_WINDOWEVENT_RESTORED:
					break;
				case SDL_WINDOWEVENT_ENTER:
					break;
				case SDL_WINDOWEVENT_LEAVE:
					break;
				case SDL_WINDOWEVENT_FOCUS_GAINED:
					break;
				case SDL_WINDOWEVENT_FOCUS_LOST:
					break;
				case SDL_WINDOWEVENT_CLOSE:
					break;
				default:
					break;
				}
				break;

			case SDL_QUIT:
				return GAME_COMMAND_EXIT;
				break;

			}
		}
	}

void GameSurfaceSDL::drawField(const CREATURE_IT &subjectCreatureIt, GameWorld *gameWorld, Field *fieldPtr, SDL_Rect_Dee &rectDraw)
{	
	SDL_Rect symbolRect = {0, 0, squareGraphicWidth, squareGraphicHeight};
	CREATURE_IT creatureIt;
	Creature *subJectCreaturePtr = subjectCreatureIt->second.get();
	
	MAP_LENGTH fx = this->focusPoint.GetX();
	MAP_LENGTH fy = this->focusPoint.GetY();

	MAP_LENGTH fieldw = this->viewFieldPtr->GetWidth();
	MAP_LENGTH fieldh = this->viewFieldPtr->GetHeight();

	MAP_LENGTH w = rectDraw.w / this->squareGraphicWidth + 1;
	MAP_LENGTH h = rectDraw.h / this->squareGraphicHeight + 1;
	MAP_LENGTH x = fx - (w / 2);
	MAP_LENGTH y = fy - (h / 2);

	MAP_LENGTH px, py, sx = 0, sy = 0;

	//sx = - (rectDraw.w % (this->squareGraphicWidth / 2));
	//sy = - (rectDraw.h % (this->squareGraphicHeight / 2));

	if(x > fieldw - w + this->fieldPadding) x = fieldw - w + this->fieldPadding;
	if(y > fieldh - h + this->fieldPadding) y = fieldh - h + this->fieldPadding;
	if(x < -this->fieldPadding) x = -this->fieldPadding;
	if(y < -this->fieldPadding) y = -this->fieldPadding;


	SDL_RenderSetViewport(this->renderer, &rectDraw);

	for(py = y; py <= y + h; py++)
	{
		for(px = x; px <= x + w; px++)
		{
			if(px >= 0 && py >= 0 && px < fieldPtr->GetWidth() && py < fieldPtr->GetHeight())
			{
				SDL_Rect blitRect = {(px - x) * squareGraphicWidth - sx, (py - y) * squareGraphicHeight - sy, squareGraphicWidth, squareGraphicHeight};

				/*
				SDL_Rect checkRect1 = {(px - x) * squareGraphicWidth - sx - 2 + 12, 30 + (py - y) * squareGraphicHeight - 2 - sy + 12, 4, 4};
				SDL_Rect checkRect2 = {(px - x) * squareGraphicWidth - sx - 2, 30 + (py - y) * squareGraphicHeight - 2 - sy , 4, 4};
				SDL_Rect checkRect3 = {(px - x) * squareGraphicWidth - sx - 6 + 12, 30 + (py - y) * squareGraphicHeight - 1 - sy , 12, 2};
				SDL_Rect checkRect4 = {(px - x) * squareGraphicWidth - sx - 1, 30 + (py - y) * squareGraphicHeight - 6 + 12 - sy , 2, 12};
				*/

				if(subJectCreaturePtr->InSight(px, py))
				{
					TAG tag = fieldPtr->GetSquare(px, py)->GetFloorTag();
					SDL_RenderCopy(renderer, floorTextures[tag], &symbolRect, &blitRect);
					if(!subJectCreaturePtr->InSight(px, py))
					{
						SDL_Rect fieldRect = {blitRect.x % 128, blitRect.y % 128, squareGraphicWidth, squareGraphicHeight};
						SDL_RenderCopy(this->renderer, unseenFieldTexture, &fieldRect, &blitRect);
					}
				}
				else
				{
					SDL_Rect fieldRect = {blitRect.x % 128, blitRect.y % 128, squareGraphicWidth, squareGraphicHeight};
					SDL_RenderCopy(this->renderer, unknownFieldTexture, &fieldRect, &blitRect);
				}

				/*
				if(fieldPtr->GetSightPass(px * 2 + 1, py * 2 + 1))
					SDL_SetRenderDrawColor(this->renderer, 255, 255, 255, 255);
				else
					SDL_SetRenderDrawColor(this->renderer, 255, 0, 0, 255);
				SDL_RenderFillRect(this->renderer, &checkRect1);

				if(fieldPtr->GetSightPass(px * 2, py * 2))
					SDL_FillRect(windowSurface, &checkRect2, SDL_MapRGBA(windowSurface->format, 255, 255, 255, 255));
				else
					SDL_FillRect(windowSurface, &checkRect2, SDL_MapRGBA(windowSurface->format, 255, 0, 0, 255));

				if(fieldPtr->GetSightPass(px * 2 + 1, py * 2))
					SDL_FillRect(windowSurface, &checkRect3, SDL_MapRGBA(windowSurface->format, 255, 255, 255, 255));
				else
					SDL_FillRect(windowSurface, &checkRect3, SDL_MapRGBA(windowSurface->format, 255, 0, 0, 255));

				if(fieldPtr->GetSightPass(px * 2, py * 2 + 1))
					SDL_FillRect(windowSurface, &checkRect4, SDL_MapRGBA(windowSurface->format, 255, 255, 255, 255));
				else
					SDL_FillRect(windowSurface, &checkRect4, SDL_MapRGBA(windowSurface->format, 255, 0, 0, 255));
				*/

			}
		}
	}

	for(creatureIt = gameWorld->GetCreatureList()->begin(); creatureIt != gameWorld->GetCreatureList()->end(); creatureIt++)
	{
		if(!creatureTextures[creatureIt->first])
		{
			updateCreatureGraphics(creatureIt);
		}

		if(subJectCreaturePtr->InSight(creatureIt->second->GetPosition().GetX(), creatureIt->second->GetPosition().GetY()))
		{
			SDL_Rect blitRect = {(creatureIt->second->GetPosition().GetX() - x) * squareGraphicWidth - sx, (creatureIt->second->GetPosition().GetY()- y) * squareGraphicHeight - sy, squareGraphicWidth, squareGraphicHeight};
			SDL_RenderCopy(renderer, creatureTextures[creatureIt->first], &symbolRect, &blitRect); 
		}
		
		/*
		if(subjectCreatureIt->second->GetLore()->GetFieldLore(0, creatureIt->second->GetPosition().GetX(), creatureIt->second->GetPosition().GetY()) > 0)
		{
			SDL_Rect blitRect = {GameSurfaceSDL::sideBarWidth + (creatureIt->second->GetPosition().GetX() - x) * squareGraphicWidth, 30 + (creatureIt->second->GetPosition().GetY()- y) * squareGraphicHeight, squareGraphicWidth, squareGraphicHeight};
			SDL_BlitSurface(creatureSurfaces[creatureIt->first], &symbolRect, windowSurface, &blitRect); 
		}
		*/
	}

	SDL_RenderSetViewport(this->renderer, NULL);

}

	void GameSurfaceSDL::FocusField(MAP_LENGTH x, MAP_LENGTH y)
	{	
		this->focusPoint.Set(x, y);
	}

	void GameSurfaceSDL::FocusField(Coordinates coord)
	{	
		this->focusPoint.Set(coord.GetX(), coord.GetY());
	}

	void GameSurfaceSDL::drawSystemMessage(void)
	{
		SDL_Rect messageRect = {0, 0, 200, 200};
		SDL_Rect messagePositon = {220, 180, 420, 380}; 
		SDL_RenderCopy(renderer, systemMessageTexture, &messageRect, &messagePositon);
	}

	void GameSurfaceSDL::drawGameMessage(void)
	{
		SDL_Rect messageRect = {0, 0, 512, 20};
		SDL_Rect messagePositon = {242, 4, 512, 20}; 
		SDL_RenderCopy(renderer, gameMessageTexture, &messageRect, &messagePositon);
	}

	void GameSurfaceSDL::drawTimeStatus(void)
	{
		SDL_Rect messageRect = {0, 0, 200, 50};
		SDL_Rect messagePositon = {10, 480, 200, 50}; 
		SDL_RenderCopy(renderer, gameTimeStatusTexture, &messageRect, &messagePositon);
	}

	void GameSurfaceSDL::SystemMessage(std::string message)
	{
		SDL_Surface *surface;
		this->currentSystemMessage = message;
		surface = TTF_RenderUTF8_Blended(font, toUTF8(this->currentSystemMessage.c_str()).c_str(), color);
		systemMessageTexture = SDL_CreateTextureFromSurface(renderer, surface);
		pushAnyKey();
		this->currentSystemMessage.erase();
		SDL_FreeSurface(surface);
	}

	void GameSurfaceSDL::GameMessage(std::string message)
	{
		SDL_Surface *boxSurface, *textSurface;
		SDL_Rect textPosition = {2, 2, 0, 0}; 
		this->currentGameMessage = message;
		if(gameMessageTexture) SDL_DestroyTexture(gameMessageTexture);
		boxSurface = SDL_CreateRGBSurface(0, 512, 20, 32, 0, 0, 0, 0);
		textSurface = TTF_RenderUTF8_Blended(font, toUTF8(this->currentGameMessage.c_str()).c_str(), color);
		SDL_BlitSurface(textSurface, NULL, boxSurface, &textPosition); 
		gameMessageTexture = SDL_CreateTextureFromSurface(renderer, boxSurface);
		SDL_FreeSurface(textSurface);
		SDL_FreeSurface(boxSurface);
	}

	void GameSurfaceSDL::updateCreatureGraphics(CREATURE_IT creatureIt)
	{
		SDL_Rect symbolRect = {0, 0, squareGraphicWidth, squareGraphicHeight};
		SDL_Surface *surface, *symbolSurface;
		char symBuf[5];

		SDL_DestroyTexture(creatureTextures[creatureIt->first]);
		creatureTextures.erase(creatureIt->first);

		surface = SDL_CreateRGBSurface(0, squareGraphicWidth, squareGraphicHeight, 32, 0, 0, 0, 0);
		Color symColor = creatureIt->second->GetSymbolColor();
		SDL_Color sdlSymCol = {(Uint8)symColor.GetRed(), (Uint8)symColor.GetGreen(), (Uint8)symColor.GetBlue(), (Uint8)symColor.GetAlpha()};
		sprintf_s(symBuf, 5, "%s", creatureIt->second->GetSymbol().c_str()); 
		SDL_Rect blitRect = {0, 0, squareGraphicWidth, squareGraphicHeight};

		symbolSurface = TTF_RenderUTF8_Blended(font, toUTF8(symBuf).c_str(), sdlSymCol);

		blitRect.x += (squareGraphicWidth - symbolSurface->w) / 2;
		blitRect.y += (squareGraphicHeight - symbolSurface->h) / 2;

		SDL_BlitSurface(symbolSurface, &symbolRect, surface, &blitRect); 
		SDL_FreeSurface(symbolSurface);

		creatureTextures.insert(std::map<ID, SDL_Texture*>::value_type(creatureIt->first, SDL_CreateTextureFromSurface(renderer, surface)));
		SDL_FreeSurface(surface);
	}


}