/*!
 * @file GameEngine.cpp
 * @brief ゲームエンジンの実装
 * @date 2013/12/17
 * @author Deskull
 * 2014 Sikabane Works.
 */

#pragma once

#include "stdafx.h"
#include "GameEngine.h"

#include "HaveGameTime.h"
#include "Creature.h"
#include "GameCampaign.h"
#include "GameLogger.h"

namespace Deeangband
{
	boost::mutex mutex;

	GameEngine::GameEngine()
	{
		gameWorld = new GameWorld();
		gameSurface = new GameSurfaceSDL(gameWorld);
		gameLogger = new GameLogger();

		GameElement::GameWorldPtr = gameWorld;
		GameElement::GameSurfacePtr = gameSurface;
		GameElement::GameLoggerPtr = gameLogger;

		Dice::Initialize();
		gameWorld->Initialize();

		this->gameSurface->SetField(gameWorld->GetField(0));
		this->gameSurface->SetSideStatusCreature(gameWorld->GetCreature(0));
		this->gameLogger->PutLog("GameEngine開始");
		Direction::Initialize();
	}

	GameEngine::~GameEngine()
	{
		delete(gameLogger);
		delete(gameSurface);
		delete(gameWorld);
	}

	void GameEngine::DrawingLoop(void)
	{
		while(true)
		{
			mutex.lock();
			this->gameSurface->UpdateTimeStatus(this->gameWorld->GetGameTime());
			this->gameSurface->UpdateSideCreatureStatus(gameWorld->GetPlayerCreature()->second.get());
			this->gameSurface->Draw(gameWorld->GetPlayerCreature());
			mutex.unlock();
			Sleep(2);
		}
	}

	PLAY_EXIT_CODE GameEngine::PlayLoop(void)
	{
		boost::asio::io_service io;
		boost::thread drawing(&GameEngine::DrawingLoop, this);
		drawing.detach();

		GAME_COMMAND commandID;
		PLAY_EXIT_CODE code = PLAY_EXIT_NONE;
		ACTION_IT actionIt;
		HaveGameTime *currentHaveGameTimeObject;
		while(code == PLAY_EXIT_NONE)
		{
			mutex.lock();
			currentHaveGameTimeObject = this->gameWorld->GetNextActionObject();
			
			code = currentHaveGameTimeObject->TurnProcess();

			ProcessDeadCreatures();
			this->gameSurface->FocusField(gameWorld->GetPlayerCreature()->second->GetPosition());
			if(!gameWorld->GetPlayerCreature()->second->IsAlive())
			{
				code = PLAY_EXIT_DEAD;
				gameSurface->SystemMessage("あなたは死にました。");
			}
			mutex.unlock();
			Sleep(2);
		}
		return PLAY_EXIT_QUIT;
	}

	bool GameEngine::CombatCreatures(Creature *attackerPtr, Creature *targetPtr)
	{
		attackerPtr->Melee(targetPtr);
		return true;
	}

	int GameEngine::ProcessDeadCreatures()
	{
		int deadNum = 0;
		CREATURE_IT creatureIt, creatureItCurrent;
		CREATURE_LIST *creatureList = gameWorld->GetCreatureList();

		creatureIt = creatureList->begin();

		while(creatureIt != creatureList->end())
		{
			creatureItCurrent = creatureIt;
			creatureIt++;
			if(!creatureItCurrent->second->IsAlive())
			{
				//!< @note プレイヤーの死亡ならば別途処理するのでスキップ、さもなくばクリーチャーの消滅。
				if(gameWorld->GetPlayerCreature() != creatureItCurrent)
				{
					gameSurface->GameMessage(creatureItCurrent->second->GetName() + "は死んだ。");
					creatureList->erase(creatureItCurrent);
				}
				deadNum++;
			}
		}

		return deadNum;
	}
}
