#include <Windows.h>
#include <Math.h>
#include <string>
using namespace std;

#include "Include\\DGLE2.h"
#include "Include\\DGLE2_EXT.h"
using namespace DGLE2;
#include "TTetris2D.h"

ENG_DYNAMIC_FUNC //This define must be included once to main CPP file of application

const E_KEYBOARD_KEY_CODES keyLeft = KEY_LEFT;
const E_KEYBOARD_KEY_CODES keyRight = KEY_RIGHT;
const E_KEYBOARD_KEY_CODES keyRotateClockwise = KEY_UP;
const E_KEYBOARD_KEY_CODES keyRotateAnticlockwise = KEY_SPACE;
const E_KEYBOARD_KEY_CODES keyHaste = KEY_DOWN;

#define APP_CAPTION		"Tetris 2D"
#define DLL_PATH		"DGLE2.dll"
#define RESOURCE_PATH	"data\\"

IEngineCore		 *pEngineCore	= NULL;
IRender			 *pRender		= NULL;
IRender2D		 *pRender2D		= NULL;
IInput			 *pInput		= NULL;

ITexture		 *pTexMarshrutka= NULL,
				 *pTexRoad		= NULL,
				 *pTexHach		= NULL;


IBitmapFont		 *pFnt			= NULL;

IResourceManager *pResourceMan	= NULL;
IGUIForms        *pGUIForms		= NULL;
IGUIEngine       *pGuiEngine	= NULL;
IDCForm			 *pForm			= NULL;

#define M_PI 3.14f

#define POLYGON_DEF 1.f/*u*/,1.f/*w*/,0.7/*r*/,0.7/*g*/,0.f/*b*/,1.f/*a*/

//TTetris2D tetris(1.0f, 4.0f, 10, 20, TRectF(590, 300, 250, 500), TColor4(124, 0, 0, 255), vTextures);
TTetris2D *tetris;
TPoint2 pointTetris(0, 0);
ISoundSample *pSnd[5];

void CALLBACK Init(void *pParametr)
{
	randomize();
	std::vector<ITexture*> vTextures;
	vTextures.resize(10);


	IResourceManager *p_res_man;
	pEngineCore->GetSubSystem(ESS_RESOURCE_MANAGER, (IEngineSubSystem *&)p_res_man);
	pEngineCore->GetSubSystem(ESS_INPUT, (IEngineSubSystem *&)pInput);
	pEngineCore->GetSubSystem(ESS_RENDER, (IEngineSubSystem *&)pRender);
	pRender->GetRender2D(pRender2D);
	
	IMusic *pm;
	p_res_man->Load("music.mp3",(IEngBaseObj*&)pm);
	pm->Play();
	pm->SetVolume(60);

	p_res_man->Load(RESOURCE_PATH"Times_New_Roman_18_Bold.dft",(IEngBaseObj*&)pFnt);
	
	p_res_man->Load(RESOURCE_PATH"road.jpg",(IEngBaseObj*&)pTexRoad,TEXTURE_LOAD_DEFAULT_2D);
	p_res_man->Load(RESOURCE_PATH"marshrutka.png",(IEngBaseObj*&)pTexMarshrutka,TEXTURE_LOAD_DEFAULT_2D);
	p_res_man->Load(RESOURCE_PATH"hach.png",(IEngBaseObj*&)pTexHach,TEXTURE_LOAD_DEFAULT_2D);
	p_res_man->Load(RESOURCE_PATH"person.png",(IEngBaseObj*&)vTextures[0],TEXTURE_LOAD_DEFAULT_2D);
	p_res_man->Load(RESOURCE_PATH"people\\gop1.png",(IEngBaseObj*&)vTextures[1],TEXTURE_LOAD_DEFAULT_2D);
	p_res_man->Load(RESOURCE_PATH"people\\gop2.png",(IEngBaseObj*&)vTextures[2],TEXTURE_LOAD_DEFAULT_2D);
	p_res_man->Load(RESOURCE_PATH"people\\gop3.png",(IEngBaseObj*&)vTextures[3],TEXTURE_LOAD_DEFAULT_2D);
	p_res_man->Load(RESOURCE_PATH"people\\gop4.png",(IEngBaseObj*&)vTextures[4],TEXTURE_LOAD_DEFAULT_2D);
	p_res_man->Load(RESOURCE_PATH"people\\gop5.png",(IEngBaseObj*&)vTextures[5],TEXTURE_LOAD_DEFAULT_2D);
	p_res_man->Load(RESOURCE_PATH"people\\gop6.png",(IEngBaseObj*&)vTextures[6],TEXTURE_LOAD_DEFAULT_2D);
	p_res_man->Load(RESOURCE_PATH"people\\gop7.png",(IEngBaseObj*&)vTextures[7],TEXTURE_LOAD_DEFAULT_2D);
	p_res_man->Load(RESOURCE_PATH"people\\gop8.png",(IEngBaseObj*&)vTextures[8],TEXTURE_LOAD_DEFAULT_2D);
	p_res_man->Load(RESOURCE_PATH"people\\gop9.png",(IEngBaseObj*&)vTextures[9],TEXTURE_LOAD_DEFAULT_2D);

	p_res_man->Load(RESOURCE_PATH"sounds\\bebela.wav",(IEngBaseObj*&)pSnd[0]);
	p_res_man->Load(RESOURCE_PATH"sounds\\dver.wav",(IEngBaseObj*&)pSnd[1]);
	p_res_man->Load(RESOURCE_PATH"sounds\\proezd.wav",(IEngBaseObj*&)pSnd[2]);
	p_res_man->Load(RESOURCE_PATH"sounds\\stoe.wav",(IEngBaseObj*&)pSnd[3]);
	p_res_man->Load(RESOURCE_PATH"sounds\\vse.wav",(IEngBaseObj*&)pSnd[4]);


	tetris = new TTetris2D (1.0f, 4.0f, 10, 20, TRectF(590, 300, 250, 500), TColor4(124, 0, 0, 255), vTextures);
	pointTetris = TPoint2(tetris->GetDrawingRect().x, tetris->GetDrawingRect().y);
	
}

void CALLBACK Free(void *pParametr)
{
	delete tetris;
}

E_KEYBOARD_KEY_CODES GetPressedKey(IInput *pInput)
{
	bool pressed = false;
	E_KEYBOARD_KEY_CODES key;
	key = keyLeft;
	pInput->GetKey(key,pressed);
	if(pressed)
		return key;
	key = keyRight;
	pInput->GetKey(key,pressed);
	if(pressed)
		return key;
	key = keyRotateClockwise;
	pInput->GetKey(key,pressed);
	if(pressed)
		return key;
	key = keyRotateAnticlockwise;
	pInput->GetKey(key,pressed);
	if(pressed)
		return key;
	key = keyHaste;
	pInput->GetKey(key,pressed);
	if(pressed)
		return key;
	return KEY_ESCAPE;
}

uint counter = 0;

void CALLBACK Process(void *pParametr)
{
	if(rand()%500 == 250)
		pSnd[rand()%5]->Play();

	static uint prs_counter = 0;
	++prs_counter;
	tetris->SetDrawingRect(TRectF(pointTetris.x + cos(counter/10.f)*20.f, pointTetris.y  + sin(counter/20.f)*5.f,
						tetris->GetDrawingRect().width, tetris->GetDrawingRect().height)); 
	
	counter++;

	if(prs_counter < 10)
		return;

	prs_counter = 0;

	switch(GetPressedKey(pInput))
	{
	case keyLeft:
		tetris->Game(ECommand_Left);
		break;
	case keyRight:
		tetris->Game(ECommand_Right);
		break;
	case keyRotateClockwise:
		tetris->Game(ECommand_RotateClockwise);
		break;
	case keyRotateAnticlockwise:
		tetris->Game(ECommand_RotateAnticlockwise);
		break;
	case keyHaste:
		tetris->Game(ECommand_Haste);
		break;
	default:
		tetris->Game(ECommand_NoCommand);
		break;
	}

	TEngWindow engWindow;
	pEngineCore->GetCurrentWin(engWindow);

	if(counter == engWindow.uiHeight)
		counter = 0;
}

void CALLBACK Render(void *pParametr)
{
	pRender2D->Begin2D();
	//внешняя часть
	TEngWindow engWindow;
	pEngineCore->GetCurrentWin(engWindow);

	TRectF rectMarshrutka = tetris->GetDrawingRect();
	rectMarshrutka = TRectF(rectMarshrutka.x - 1.1f/3.0f * rectMarshrutka.width, rectMarshrutka.y - 5.5f/9.3f * rectMarshrutka.height,
							rectMarshrutka.width + 2*1.15f/3.0f * rectMarshrutka.width, (5.5f+1.2f+9.3f)/9.3f * rectMarshrutka.height);
	TRectF rectHack = tetris->GetDrawingRect();
	rectHack = TRectF( rectHack.x, (rectHack.y + rectMarshrutka.y) * 2.1 / 3,
				(float) (rectMarshrutka.width * 0.167f), (float) (rectMarshrutka.height * 0.167f) );
	
	pTexRoad->Draw2D((int)0, counter - engWindow.uiHeight, engWindow.uiWidth, engWindow.uiHeight);
	pTexRoad->Draw2D((int)0, counter, engWindow.uiWidth, engWindow.uiHeight);
	
	pTexMarshrutka->Draw2D((int)rectMarshrutka.x, (int)rectMarshrutka.y, (uint)rectMarshrutka.width, (uint)rectMarshrutka.height);
	pTexHach->Draw2D((int) (rectHack.x * 1.02), (int) (rectHack.y * 1.04),
					(uint) (rectMarshrutka.width * 0.19), (uint) (rectMarshrutka.height * 0.08));

	//pRender->EnableScissor(TRectF(259,270,259,136));
	//pRender->DisableScissor();
	 
	static bool lose = false;
	tetris->Draw(pRender2D, pRender);
	if(tetris->IsLoseGame() && !lose)
	{
		MessageBoxA(NULL,"You lose game!", APP_CAPTION, MB_OK | MB_SETFOREGROUND);
		lose = true;
	}
	
	string strScore = "Score: " + ValueToStr(tetris->GetScore());
	unsigned int txt_w, txt_h;
	pFnt->GetTextDimensions(strScore.c_str(),txt_w,txt_h);
	pFnt->Draw2D((int) (rectMarshrutka.x + (rectMarshrutka.width - txt_w) / 2), (int) (rectMarshrutka.y + rectMarshrutka.height * 0.03f),
					strScore.c_str(), TColor4(0,0,255,255));
	
	pRender2D->End2D();
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
	if(GetEngine(DLL_PATH,pEngineCore))
	{
		if(SUCCEEDED(pEngineCore->InitializeEngine(NULL,APP_CAPTION,TEngWindow(900, 900, false))))
		{
			pEngineCore->AddProcedure(EPT_INIT,	&Init);
			pEngineCore->AddProcedure(EPT_FREE,	&Free);
			pEngineCore->AddProcedure(EPT_PROCESS, &Process);
			pEngineCore->AddProcedure(EPT_RENDER,	&Render);
			pEngineCore->StartEngine();
		}
		FreeEngine();
	}
	else MessageBoxA(NULL,"Couldn't load \""DLL_PATH"\"!", APP_CAPTION, MB_OK | MB_ICONERROR | MB_SETFOREGROUND);
	return 0;
}