#include "gameMap.h"

using namespace SE;

TMapCharacter::TMapCharacter() : 
	Pos(ZeroVec3), 
	RotationMatrix(IdentityMatrix), 
	Direction(vec3(0.0f, 0.0f, 1.0f)),
	Destination(ZeroVec3), 
	VectorToDestination(ZeroVec3),
	Velocity(0.0f)
{
}

void TMapCharacter::SetPos(vec3& pos)
{
	Pos = pos;
}

void TMapCharacter::GoToDestination(vec3& dest)
{
	Destination = vec3(dest.v[0], 0.0f, dest.v[2]);
	Velocity = 0.002f;
}

void TMapCharacter::Update(cardinal timer)
{
	const float CONST_DISTANCE_SLOW_DOWN = 1.0f;
	const float CONST_DISTANCE_STOP = 0.1f;
	const float CONST_ROTATION_ANGLE_STEP = pi/200;

	VectorToDestination = (Destination - Pos);
	VectorToDestination.v[1] = 0.0f;
	VectorToDestination = Normalize(VectorToDestination);

	if (!IsFloatEqual(Velocity, 0.0f))
	{
		float cosa = DotProduct(VectorToDestination, Direction);

		float alpha = acosf(cosa);
		
		if (alpha <= CONST_ROTATION_ANGLE_STEP * timer)
		{
			Direction = VectorToDestination;
		}
		else
		{
			vec3 n = Normalize(CrossProduct(Direction, VectorToDestination));
		
			float sinb = sinf(CONST_ROTATION_ANGLE_STEP * timer / 2.0f);
			float cosb = cosf(CONST_ROTATION_ANGLE_STEP * timer / 2.0f);
			
			vec4 q;
			q.v[0] = n.v[0] * sinb;
			q.v[1] = n.v[1] * sinb;
			q.v[2] = n.v[2] * sinb;
			q.v[3] = cosb;
			mat3 rmat = mat3(q);
			RotationMatrix *= rmat;
			Direction = rmat * Direction;

		}
	}
	
	if (!(Pos == Destination))
	{

		float dist = sqrtf((Pos.v[0] - Destination.v[0])*(Pos.v[0] - Destination.v[0]) + 
			(Pos.v[1] - Destination.v[1])*(Pos.v[1] - Destination.v[1]) + 
			(Pos.v[2] - Destination.v[2])*(Pos.v[2] - Destination.v[2]));
	
		if (dist > CONST_DISTANCE_SLOW_DOWN)
		{
			Pos = Pos + timer*Velocity*Direction;
		}
		else if (dist > CONST_DISTANCE_STOP && dist <= CONST_DISTANCE_SLOW_DOWN)
		{
			Pos = Pos + 0.5f*timer*Velocity*Direction;
		}
		else
		{
			Pos = Destination;
			Velocity = 0.0f;
			VectorToDestination = ZeroVec3;

		}
	
	}
}

vec3 TMapCharacter::GetPos()
{
	return Pos;
}

mat3 TMapCharacter::GetRotationMatrix()
{
	return RotationMatrix;
}

void TGameMap::LoadMap()
{
	Land = new TSimpleLandClass;
	Land->LoadFromFile(std::string("landscapes/out.ls1"));
	Land->SetTexture(std::string("landscapes/out.bmp"));
	Land->Scale(0.005f);

	StaticModelArr.resize(4);
	StaticModelArr[0].LoadModel("bt_box_yellow.lm1");
	StaticModelArr[1].LoadModel("bt_box_red.lm1");
	StaticModelArr[2].LoadModel("bt_box_blue.lm1");
	StaticModelArr[3].LoadModel("bt_box_yellow.lm1");
	
	StaticModelArr[0].ScaleModel(2.0);
	StaticModelArr[0].RotateModel(mat3(vec4(0.0, sin(pi/6), 0.0, cos(pi/6))));
	StaticModelArr[0].MoveModel(vec3(-1.0f, 0.13f, 4.3f));

	StaticModelArr[1].ScaleModel(2.0);
	StaticModelArr[1].RotateModel(mat3(vec4(-sin(pi / 3), 0.0, 0.0, cos(pi / 3))));
	StaticModelArr[1].RotateModel(mat3(vec4(0.0, -sin(pi / 4), 0.0, cos(pi / 4))));
	StaticModelArr[1].MoveModel(vec3(-6.0f, 0.0f, 8.8f));

	StaticModelArr[2].ScaleModel(2.0);
	StaticModelArr[2].MoveModel(vec3(-1.5f, 0.23f, 7.8f));

	StaticModelArr[3].ScaleModel(2.0);
	StaticModelArr[3].MoveModel(vec3(0.f, 0.4f, 0.f));


	StaticModelArr[0].UpdateVBO();
	StaticModelArr[1].UpdateVBO(); 
	StaticModelArr[2].UpdateVBO();
	StaticModelArr[3].UpdateVBO();

	//StaticModelArr[0].SetShaderTranslateVector(vec3(-1.0f, 0.23f, 6.3f));
	PlayerChar = new TLiteModel;
	PlayerChar->LoadModel("bt_cone.lm1");

	AnimModel = new TAnimModel;
	AnimModel->LoadModel("bonemodel.lm1");

	animSeq = 0;
	//AnimModel->ApplySequence("bonemodel.an1", animSeq);

	GirlText = new TAnimModel;
	GirlText->LoadModel("girl.lm1");
	//GirlText->ScaleModel(0.1f);
	//GirlText->MoveModel(vec3(0,4,0));
	//GirlText->UpdateVBO();
	//GirlText->ApplySequence("girl.an1", 0);
	
	MapChar.SetPos(vec3(0.0f, 0.0f, 10.0f));

	day = false;

}

void TGameMap::FreeMap()
{
	if (Land)
	{
		delete Land;
		Land = NULL;
	}

	
	if (PlayerChar)
	{
		delete PlayerChar;
		PlayerChar = NULL;
	}

	if (AnimModel)
	{
		delete AnimModel;
		AnimModel = NULL;
	}

	if (GirlText)
	{
		delete GirlText;
		GirlText = NULL;
	}

	StaticModelArr.clear();
}

TSimpleLandClass* TGameMap::GetLand()
{
	return Land;
}

void TGameMap::DrawVBO()
{
	
	Land->DrawVBO();

	if (day)
	{
		Renderer->PushShader("Directlight");
	}
	else
	{
		Renderer->PushShader("Directlight3");
	}
	for (TLiteModelArr::iterator i = StaticModelArr.begin(); i != StaticModelArr.end(); ++i)
	{
		//i->DrawImmediate();
		i->DrawVBO();
	}
	Renderer->PopShader();

	//PlayerChar->DrawVBO();

	//AnimModel->DrawVBO();

	//GirlText->DrawVBO();
	
}

cardinal timeForSeq = 0;

void TGameMap::Update(cardinal timer)
{

	vec4 quat = vec4(0, sin(timer / 2000.f), 0, cos(timer / 2000.f));

	mat3 rotate(quat);

	StaticModelArr[3].RotateModel(rotate);
	StaticModelArr[3].UpdateVBO();


	/*
	MapChar.Update(timer);


	vec3 vecFrom, vecTo;
	vec3 pos = Land->CalcVerticalCrossing(MapChar.GetPos());

	PlayerChar->SetShaderTranslateVector(pos);
	PlayerChar->SetShaderRotateMatrix(MapChar.GetRotationMatrix());

	timeForSeq += timer;

	if (timeForSeq >= 2000)
	{
		timeForSeq = 0;

		if (animSeq != 12)
		{
		animSeq = 12;
		//animSeq+= 1;


		if (animSeq >= 100)
		{
			animSeq = 0;
		}

		//GirlText->ApplySequence("girl.an1", animSeq);
		//GirlText->UpdateVBO();
		}
	}*/

	
	
	

	//AnimModel->ApplySequence("bonemodel.an1", animSeq);
	//AnimModel->UpdateVBO();

	
}

void TGameMap::PlayerClicked(int x, int y)
{
	/*
	vec3 vecFrom, vecTo;
	SalmonRender->GetVectorOutOfCursor(x, y, vecFrom, vecTo);

	vec3 r = Land->CalcCrossing(vecFrom, vecTo);

	MapChar.GoToDestination(r);
	*/
}