/*
 *  FSPlayer.cpp
 *  FeatheredSoccer
 *
 *  Created by Ludovico Rossi on 23/08/04.
 *  Copyright 2004 __MyCompanyName__. All rights reserved.
 *
 */

#include "FSPlayer.h"

FSPlayer::FSPlayer(ModelType *theModel, FSPlayers thePlayer, FSColor theBodyColor, FSColor theLegsColor)
{
	model = theModel;
	player = thePlayer;
	position = FSVector(0.0, 0.0, 0.0);
	acceleration = FSVector(0.0, 0.0, 0.0); 
	velocity = FSVector(0.0, 0.0, 0.0);
	speed = 2000.0;
	angle = 0.0;
	radius = 350.0;
	updateBall = false;
	moveDelay.endTime = -1;
	moveDelay.time = 0;
	status = FS_WAIT;
	walking = false;
	timeAnim = 0.0;
	pose = 0;
	addTemp = FSVector(0,0,0);
	wasAdd = false;
	add = true;
	dontMove = false;
	tackling = false;
	tacklingTime = 0;
	falling = false;
	fallingTime = 0;
	timer = -1;
	timer2 = -1;
	
	//colorMatrix = { {1.0, 0.5, 0.0}, {1.0, 0.5, 0.0}, {0.0, 0.0, 0.0}, {0.8, 0.8, 0.8}, {0.5, 0.5, 0.0} };
	
	/* orange */
	colorMatrix[0][0] = 1.0;
	colorMatrix[0][1] = 0.5;
	colorMatrix[0][2] = 0.0;
	
	/* black */
	colorMatrix[1][0] = 0.0;
	colorMatrix[1][1] = 0.0;
	colorMatrix[1][2] = 0.0;
	
	/* white */
	colorMatrix[2][0] = 0.8;
	colorMatrix[2][1] = 0.8;
	colorMatrix[2][2] = 0.8;
	
	/* body */
	colorMatrix[3][0] = theBodyColor.r;
	colorMatrix[3][1] = theBodyColor.g;
	colorMatrix[3][2] = theBodyColor.b;
	
	/* face */
	colorMatrix[4][0] = 0.5;
	colorMatrix[4][1] = 0.5;
	colorMatrix[4][2] = 0.0;
	
	/* feet */
	colorMatrix[5][0] = 1.0;
	colorMatrix[5][1] = 0.5;
	colorMatrix[5][2] = 0.0;
	
	return;
}

void FSPlayer::Init()
{
	acceleration = FSVector(0.0, 0.0, 0.0); 
	velocity = FSVector(0.0, 0.0, 0.0);
	angle = 0.0;
	radius = 350.0;
	updateBall = false;
	moveDelay.endTime = -1;
	moveDelay.time = 0;
	status = FS_WAIT;
	walking = false;
	timeAnim = 0.0;
	pose = 0;
	addTemp = FSVector(0,0,0);
	wasAdd = false;
	add = true;
	dontMove = false;
	tackling = false;
	tacklingTime = 0;
	falling = false;
	fallingTime = 0;
	timer = -1;
	timer2 = -1;
}	

void FSPlayer::Draw()
{
	glPushMatrix();
	
	glTranslatef(position.x, position.y, position.z);
	if(tackling)
		glRotatef(tackleAngle, 0.0, 1.0f, 0.0);
	else if(falling)
		glRotatef(fallAngle, 0.0, 1.0f, 0.0);
	else
		glRotatef(angle, 0.0, 1.0f, 0.0);
	/*
	for(int i = 0; i < model->numOfObjects; i++)
    {
        // Make sure we have valid objects just in case. (size() is in the vector class)
        if(model->pObject.size() <= 0) break;
		
        // Get the current object that we are displaying
        t3DObject *pObject = &model->pObject[i];
		
		//printf("name:%s", pObject->strName);
		
		
		if(!strcmp(pObject->strName, "Body Head R_Eye R_Irid\n") || !strcmp(pObject->strName, "Body Head L_Eye L_Irid\n"))
			glColor3f(0.0, 0.0, 0.0);
		else if(!strcmp(pObject->strName, "Body Head R_Eye\n") || !strcmp(pObject->strName, "Body Head L_Eye\n"))
			glColor3f(0.8, 0.8, 0.8);
		else if(!strcmp(pObject->strName, "Body Head Beak\n"))
			glColor3f(1.0, 0.5, 0.0);
		else
			glColor3f(0.5, 0.5, 0.0);
		   
		// Turn off texture mapping and turn on color
		glDisable(GL_TEXTURE_2D);
		
		
        // This determines if we are in wire frame or normal mode
        glBegin(GL_TRIANGLES);                    // Begin drawing with our selected mode (triangles or lines)
		
		// Go through all of the faces (polygons) of the object and draw them
		for(int j = 0; j < pObject->numOfFaces; j++)
		{
			// Go through each corner of the triangle and draw it.
			for(int whichVertex = 0; whichVertex < 3; whichVertex++)
			{
				// Get the vertex index for each point of the face
				int vertIndex = pObject->pFaces[j].vertIndex[whichVertex];
				
				// Give OpenGL the normal for this vertex.
				glNormal3f(pObject->pNormals[ vertIndex ].x, pObject->pNormals[ vertIndex ].y, pObject->pNormals[ vertIndex ].z);
                
				// If the object has a texture associated with it, give it a texture coordinate.
				
				/*
				 // Make sure there is a valid material/color assigned to this object.
				 // You should always at least assign a material color to an object, 
				 // but just in case we want to check the size of the material list.
				 // if the size is at least one, and the material ID != -1,
				 // then we have a valid material.
				 if(model.pMaterials.size() && pObject->materialID >= 0) 
				 {
					 // Get and set the color that the object is, since it must not have a texture
					 BYTE *pColor = model.pMaterials[pObject->materialID].color;
					 
					 // Assign the current color to this model
					 glColor3ub(pColor[0], pColor[1], pColor[2]);
				 }
				 
				 */
				
				////////float x = pObject->pVerts[ vertIndex ].z;
				/*if(x < oldMaxX)
					x = oldMaxX;*/
				   
				// Pass in the current vertex of the object (Corner of current face)
				///////glVertex3f(pObject->pVerts[ vertIndex ].x, pObject->pVerts[ vertIndex ].y, x);
				/*
				if(x > maxX)
					maxX = x;*/
		/*	}
		}
		
        glEnd();                                // End the drawing
		
		//oldMaxX = maxX;
	}
	*/
		
		int realPose = pose;
		
		if(realPose == 2)
			realPose = 0;
		else if(realPose == 3)
			realPose = 2;
		
		if(tackling)
			realPose = 3;
		
		if(falling)
			realPose = 4;
		
		if(angle > 180)
		{
			short orderMatrix[] = {5, 3, 4, 0, 2, 1};
			model[realPose].Draw(colorMatrix, orderMatrix);
		}
		else
		{
			short orderMatrix[] = {5, 1, 2, 0, 3, 4};
			model[realPose].Draw(colorMatrix, orderMatrix);
		}
		
	glPopMatrix();
	return;
}

void FSPlayer::moveToPoint(int x, int z, FSBall *ball)
{
	float deltaZPerDeltaX = ( z - (position.z)) / ( x - (position.x));
	
	float theX = (cos (atan(  deltaZPerDeltaX  ))  ) * speed;
	
	if(position.x > x)
		theX = -theX;
	
	float theZ = (sin (atan( -abs( deltaZPerDeltaX  )))  ) * speed;
	
	if(position.z < z)
		theZ = -theZ;
	
	velocity = FSVector( theX, 0, theZ);
	
	//angle = (acos((position.z - z) / sqrt( ((x - position.x) * (x - position.x)) + ((z - position.z) * (z - position.z)) ) ) * 360) / 6.28;
	//angle = (asin(abs(position.x - x) / sqrt( ((x - position.x) * (x - position.x)) + ((z - position.z) * (z - position.z)) ) ) * 360) / 6.28;
	
	//angle = (atan( ball->position.z - (position.z)) / ( ball->position.x - (position.x)) * 360 )/ 6.28;
	
	angle = (atan( abs(deltaZPerDeltaX))* 360) / 6.28;
	angle += 90;
	if(position.z > z && position.x > x)
		angle = 90 - (angle - 90);
	else if(position.z < z && position.x < x)
		angle = 360 - angle;
	else if(position.x < x)
		angle = 180 + angle;
	else if(position.z > z)
		angle = 180 + angle;

	
	//angle = asin(theZ / speed); //(atan(  deltaZPerDeltaX  ) * 360) / 6.28;//(atan( deltaZPerDeltaX  ) * 360) / 6.28;
	//if(position.x > x)
	//	angle += 3.14; 
	
	updateBall = true;
}

void FSPlayer::jump()
{
	if(velocity.y == 0 && acceleration.y == 0)
	{
		acceleration.y = -8000.0;
		velocity.y = 3000.0;
	}
}

void FSPlayer::moveGoalKeeper(int deltaT, FSBall *ball, int factor)
{
	int goalZ = (player <= 5) ? 0 : -19000;
	
	if((player <= 5) && position.z < -600.0)
	{
		moveToPoint(4000, -570, ball);
		return;
	}
	
	if(ball->velocity.z)
	{
		int shoot = (ball->velocity.z < -1.0) ? (ball->position.x + (ball->velocity.x * ((goalZ - ball->position.z) / ball->velocity.z))) 
										: ball->position.x;
		
		if(factor <= 10)  
		{
			if(position.x > (shoot + 50))
			{
				if(position.x > 3000)
					move(0.0, 1.0, 1.0);
				else
				{
					move(0.0, 0.0, 1.0);
					angle = (player <= 5) ? 0.0 : 180.0;
				}
			}
			else if(position.x < (shoot - 50))
			{
				if(position.x < 5000)
					move(0.0, -1.0, 1.0);
				else
				{
					move(0.0, 0.0, 1.0);
					angle = (player <= 5) ? 0.0 : 180.0;
				}
			}
			else
			{
				move(0.0, 0.0, 1.0);
				angle = (player <= 5) ? 0.0 : 180.0;
			}
			
			int zDistance = abs(ball->position.z - position.z);
				
			if(zDistance < 4000.0)
			{
				if(ball->position.y > 500.0)
					jump();
				
				if(position.x > (shoot + 50) && (position.x > 3000))
					move(0.0, 1.0, 1.5);
				else if(position.x < (shoot - 50) && (position.x < 5000))
					move(0.0, -1.0, 1.5);
			}
		}
	}
	else
		move(0.0, 0.0, 1.0);
	//position.x = (ball->velocity.x + ball->position.x) * ((-19000 - ball->position.z) / ball->velocity.z);
}

void FSPlayer::move(int deltaT, FSGround *field, FSBall *ball)
{	
	float time = deltaT / 1000.0f;
	
	if(ball->takenBy == player)
	{
		if(position.x < 300.0)
		{
			if(velocity.x < 0.0)
				velocity.x = 0.0;
			
			position.x = 300.0;
		}
		else if(position.x > 7700.0)
		{
			if(velocity.x > 0.0)
				velocity.x = 0.0;
			
			position.x = 7700.0;
		}
		
		if(position.z < -18650.0)
		{
			if(velocity.z < 0.0)
				velocity.z = 0.0;
			
			position.z = -18650.0;
		}
		else if(position.z > -350.0)
		{
			if(velocity.z > 0.0)
				velocity.z = 0.0;
			
			position.z = -350.0;
		}
	}
	else
	{
		if(position.x < 0.0)
		{
			if(velocity.x < 0.0)
				velocity.x = 0.0;
			
			position.x = 0.0;
		}
		else if(position.x > 8000.0)
		{
			if(velocity.x > 0.0)
				velocity.x = 0.0;
			
			position.x = 8000.0;
		}
		
		if(position.z < -19000.0)
		{
			if(velocity.z < 0.0)
				velocity.z = 0.0;
			
			position.z = -19000.0;
		}
		else if(position.z > 0.0)
		{
			if(velocity.z > 0.0)
				velocity.z = 0.0;
			
			position.z = 0.0;
		}
	}
	
	
	if(velocity.y != 0.0 && position.y < 300.0)
	{
		position.y = 300.0;
		velocity.y = 0.0;
		acceleration.y = 0.0;
	}
	
	if(timer != -1)
	{
		timer -= time;
		
		if(timer < 0)
			timer = -1;
	}
	
	if(timer2 != -1)
	{
		timer2 -= time;
		
		if(timer2 < 0)
			timer2 = -1;
	}
	
	if(status == FS_DRIBBLING)
	{
		dribblingTime -= time;
		if(dribblingTime < 0.0)
		{
			status = nextStatus;
		}
	}
	
	if(falling)
	{
		fallingTime += time;
		if(fallingTime > 3.0)
		{
			falling = false;
			fallingTime = 0;
		}
		return;
	}
	
	if(velocity.Length() != 0 && !walking)
	{
		timeAnim = 0;
		pose = 0;
		walking = true;
	}
	else if(velocity.Length() == 0 && walking)
	{
		pose = 0;
		walking = false;
	}
	else if(walking)
	{
		timeAnim += time;
		if(timeAnim > 0.1)
		{
			(pose == 3) ? pose = 0 : pose++;
			timeAnim = 0;
		}
	}
	
	if(dontMove)
	{
		dontMove = false;
		return;
	}
	
	velocity += acceleration * time;
	
	FSVector theVelocity;
	
	if(tackling)
	{
		tacklingTime += time;
		theVelocity = tackleVelocity;
		if(tacklingTime > 0.5)
		{
			tackling = false;
			tacklingTime = 0;
		}
	}
	else
	{
		theVelocity = velocity;
	}
	
	/*
	if(add)
	{
		//if(addTemp.x != -theVelocity.x && addTemp.z != -theVelocity.z)
		theVelocity = addTemp;
		
		if(theVelocity.x > 0)
			position.x += time * 6000;
		else if(theVelocity.x < 0)
			position.x -= time * 6000;
		
		if(theVelocity.z > 0)
			position.z += time * 6000;
		else if(theVelocity.z < 0)
			position.z -= time * 6000;
		
		/*else
			theVelocity = FSVector(0,0,0);*/
	/*	addTemp = FSVector(0,0,0);
		wasAdd = true;
		add = false;
	}
	else if(wasAdd)
	{
		status = FS_WAIT;
		wasAdd = false;
	}*/
	
	position += theVelocity * time + acceleration * (time*time*0.5);
	
	if ((ball->position - position).Length() <= (ball->size + radius))
	{
		
		/*int h = 900;
		if(angle == 45)
			h = 500;*/
		
		if(ball->takenBy == player)
			ball->velocity = FSVector( -(2500 * sin((2*3.14*angle)/360)), 600,  -(2500 * cos((2*3.14*angle)/360)));
		else
		{
			ball->takenBy = player;
			updateBall = true;
		}
		
		/*if ((ball->velocity).Length() == 0)
		{
			//puck->velocity = -puck->velocity;
			updateBall = true;
			
		}
		else 
		{
			updateBall = true;
			ball->takenBy = player;
		}*/
	}
	
	if(updateBall && (ball->takenBy == player))
	{
		updateBall = false;
		ball->velocity = FSVector(0,0,0);
		ball->position = FSVector(position.x + -(500 * sin((2*3.14*angle)/360)), position.y - 200.0, position.z + -(500 * cos((2*3.14*angle)/360)));
	}
}

void FSPlayer::move(float x, float y, float scale)
{
	if(x == 1.0 && y == 0.0) // move right
	{
		velocity = FSVector(0.0, velocity.y, -speed * scale);
		
		if(angle != 0.0)
		{
			angle = 0.0;
			updateBall = true;
		}
	}
	else if(x == -1.0 && y == 0.0) // move left
	{
		velocity = FSVector(0.0, velocity.y, speed * scale);
		
		if(angle != 180.0)
		{
			angle = 180.0;
			updateBall = true;
		}
	}
	else if(x == 0.0 && y == 1.0) // move up
	{
		velocity = FSVector(-speed * scale, velocity.y, 0.0);
		if(angle != 90.0)
		{
			angle = 90.0;
			updateBall = true;
		}
	}
	else if(x == 0.0 && y == -1.0) // move down
	{
		velocity = FSVector(speed * scale, velocity.y, 0.0);
		if(angle != 270.0)
		{
			angle = 270.0;
			updateBall = true;
		}
	}
	else if(x == 1.0 && y == 1.0) // move up and right
	{
		velocity = FSVector((-speed * scale) / 1.5, velocity.y, (-speed * scale) / 1.5);
		if(angle != 45.0)
		{
			angle = 45.0;
			updateBall = true;
		}
	}
	else if(x == -1.0 && y == 1.0) // move up and left
	{
		velocity = FSVector((-speed * scale) / 1.5, velocity.y, (speed * scale) / 1.5);
		if(angle != 135.0)
		{
			angle = 135.0;
			updateBall = true;
		}
	}
	else if(x == 1.0 && y == -1.0) // move down and right
	{
		velocity = FSVector((speed * scale) / 1.5, velocity.y, (-speed * scale) / 1.5);
		if(angle != 315.0)
		{
			angle = 315.0;
			updateBall = true;
		}
	}
	else if(x == -1.0 && y == -1.0) // move down and left
	{
		velocity = FSVector((speed * scale) / 1.5, velocity.y, (speed * scale) / 1.5);
		if(angle != 225.0)
		{
			angle = 225.0;
			updateBall = true;
		}
	}
	else // stop
		velocity = FSVector(0.0, velocity.y, 0.0);
}

void FSPlayer::Load()
{
	
}


void FSPlayer::Unload()
{
	
}