#include "cGame.h"
#include "cPlayer.h"
#include "cSign.h"
#include "MediaVars.h"
#include "cHeart.h"
#ifdef WIN32
#define CLOCKS_OS 1
#elif __APPLE__
#define CLOCKS_OS .33
#endif
cPlayer::cPlayer(cGame *g, double xx, double yy)
{
	game = g;
	x = xx;
	y = yy;
	depth = 0;
	collide.SetPosition(xx,yy);
	collide.SetLeft(12);
	collide.SetTop(48);
	collide.SetRight(52);
	collide.SetBottom(64);
	facing = false;
	objectType = PLAYER;
	destroyed = false;
	invincible = false;
	bodyVisible = true;
	visible = true;
	flashNextTime = clock()+3600*CLOCKS_PER_SEC;
	invincibleEndTime = clock()+3600*CLOCKS_PER_SEC;
	fallDisappearTime = clock()+3600*CLOCKS_PER_SEC;
	fallRoomChangeTime = clock()+3600*CLOCKS_PER_SEC;
	brainlessTimer = -1;
	falling = false;
	nearSign = false;
	signObject = NULL;
	doorObject = NULL;
	readingSign = false;
	nearDoor = false;
	leftKey = sf::Key::Left;
	upKey = sf::Key::Up;
	rightKey = sf::Key::Right;
	downKey = sf::Key::Down;
	if (game->GetCurrentLevel() > 1 && !game->PlayerHasBrain())
		brainlessTimer = clock();
	iAmDead = false;
	animation_tick = 0;
	animation_frame = 0;
}

void cPlayer::Update()
{
	animation_tick = 0;
	if (falling)
	{
		if (visible)
			if (clock() >= fallDisappearTime)
			{
				visible = false;
				game->PlaySound(sndFall);
			}
		if (clock() >= fallRoomChangeTime)
			game->GoToNextLevel();
		return;
	}
	if (brainlessTimer != -1 && clock() >= brainlessTimer)
	{
		brainlessTimer += 3*CLOCKS_PER_SEC*CLOCKS_OS;
		vector<sf::Key::Code> vctr;
		vctr.push_back(sf::Key::Left);
		vctr.push_back(sf::Key::Up);
		vctr.push_back(sf::Key::Right);
		vctr.push_back(sf::Key::Down);
		for(int i=0;i<25;i++)
		{
			int q = rand() % 4;
			sf::Key::Code temp = vctr[q];
			vctr[q] = vctr[0];
			vctr[0] = temp;
		}
		leftKey = vctr[0];
		upKey = vctr[1];
		rightKey = vctr[2];
		downKey = vctr[3];
		vctr.clear();
		//delete &vctr;
	}
	if (!readingSign)
	{
		if (game->GetWindow()->GetInput().IsKeyDown(leftKey))
		{
			if (!facing)
			{
				facing = !facing;
				sprPlayer0->FlipX(facing);
				sprPlayer1->FlipX(facing);
				sprPlayer2->FlipX(facing);
				sprPlayerWithBrain0->FlipX(facing);
				sprPlayerWithBrain1->FlipX(facing);
				sprPlayerWithBrain2->FlipX(facing);
			}	
			if (!IsObjectAt(x-4,y,BRICK) && !IsObjectAt(x-4,y,SIGN) && !IsObjectAt(x-4,y,DOOR))
				x -= 4;
			animation_tick = .087;
		}
		if (game->GetWindow()->GetInput().IsKeyDown(rightKey))
		{
			if (facing)
			{
				facing = !facing;
				sprPlayer0->FlipX(facing);
				sprPlayer1->FlipX(facing);
				sprPlayer2->FlipX(facing);
				sprPlayerWithBrain0->FlipX(facing);
				sprPlayerWithBrain1->FlipX(facing);
				sprPlayerWithBrain2->FlipX(facing);
			}
			if (!IsObjectAt(x+4,y,BRICK) && !IsObjectAt(x+4,y,SIGN)  && !IsObjectAt(x+4,y,DOOR))
				x += 4;
			animation_tick = .087;
		}
		if (game->GetWindow()->GetInput().IsKeyDown(upKey))
		{
			if (!IsObjectAt(x,y-4,BRICK) && !IsObjectAt(x,y-4,SIGN) && !IsObjectAt(x,y-4,DOOR))
				y -= 4;
			animation_tick = .087;
		}
		if (game->GetWindow()->GetInput().IsKeyDown(downKey))
		{
			if (!IsObjectAt(x,y+4,BRICK) && !IsObjectAt(x,y+4,SIGN) && !IsObjectAt(x,y+4,DOOR))
				y += 4;
			animation_tick = .087;
		}
	}
	cObject* tempObj;
	if (!invincible)
	{
		tempObj = GetObjectAt(x,y,ZOMBIEGHOST);
		if (tempObj != NULL)
		{
			game->PlaySound(sndHurt);
			game->ChangePlayerHeart(-1);
			if (game->GetPlayerHeart() < 0)
				return;
			tempObj->Destroy();
			invincible = true;
			invincibleEndTime = clock()+3*CLOCKS_PER_SEC/2*CLOCKS_OS;
			flashNextTime = clock()+CLOCKS_PER_SEC/8*CLOCKS_OS;
		}
	}
	tempObj = GetObjectAt(x,y,HEART);
	if (tempObj != NULL)
	{
		game->PlaySound(sndGetHeart);
		game->StatIncrease(ST_HEART);
		game->ChangePlayerHeart(1);
		((cHeart*)tempObj)->Destroy(true);
	}
	tempObj = GetObjectAt(x,y,BRAIN);
	if (tempObj != NULL)
	{
		game->PlaySound(sndGetBrain);
		brainlessTimer = -1;
		game->ObtainedBrain();
		tempObj->Destroy();
		leftKey = sf::Key::Left;
		upKey = sf::Key::Up;
		rightKey = sf::Key::Right;
		downKey = sf::Key::Down;
	}
	if (IsObjectAt(x,y,HOLE))
	{
		falling = true;
		fallDisappearTime = clock()+3*CLOCKS_PER_SEC/4*CLOCKS_OS;
		fallRoomChangeTime = clock()+3*CLOCKS_PER_SEC/2*CLOCKS_OS;
	}
	if (clock() >= flashNextTime)
	{
		bodyVisible = !bodyVisible;
		flashNextTime += CLOCKS_PER_SEC/8*CLOCKS_OS;
	}
	if (clock() >= invincibleEndTime)
	{
		flashNextTime = clock()+3600*CLOCKS_PER_SEC*CLOCKS_OS;
		if (game->GetPlayerHeart() <= 0)
		{
			game->StatIncrease(ST_DIED);
			//MessageBox(0,"BAZINGA","BAZINGA",0);
			game->SetState(CS_LOSE);//iAmDead = true;
		}
		bodyVisible = true;
		invincible = false;
	}
	// SIGN STUFF!
	nearSign = false;
	signObject = NULL;
	for(unsigned int i=0;i<game->GetObjectVector()->size();i++)
		{
			cObject *o = game->GetObjectVector()->at(i);
			if (o->GetType() != SIGN)
				continue;
			if (point_distance(x,y,o->GetX(),o->GetY()) < 64)
			{
				nearSign = true;
				signObject = o;
				break;
			}
		}
	if (nearSign)
	{
		if (game->IsKeyPressed(sf::Key::Space))
		{
			((cSign*)signObject)->SetAsRead();
			 readingSign = !readingSign;
		}
	}
	// DOOR STUFF
	nearDoor = false;
	doorObject = NULL;
	for(unsigned int i=0;i<game->GetObjectVector()->size();i++)
		{
			cObject *o = game->GetObjectVector()->at(i);
			if (o->GetType() != DOOR)
				continue;
			if (point_distance(x,y,o->GetX(),o->GetY()) < 52)
			{
				nearDoor = true;
				doorObject = o;
				break;
			}
		}
	if (nearDoor)
	{
		if (game->IsKeyPressed(sf::Key::Space))
		{
			doorObject->Destroy();
			doorObject = NULL;
			game->PlaySound(sndDestroy);
			game->StatIncrease(ST_DOOR);
			if (game->GetCurrentLevel() == 1 && !game->PlayerHasBrain())
				brainlessTimer = clock(); // Scramble controls immediately
		}
	}
	animation_frame += animation_tick;
	//
	collide.SetPosition(x,y);
	depth = (collide.GetY()+32);
}

void cPlayer::Draw()
{
	if (visible)
	{
		if (bodyVisible)
		{
			sf::Sprite* spr = NULL;
			if (animation_frame >= 4)
				animation_frame -= 4;
			if (game->PlayerHasBrain())
			{
				switch((int) floor(animation_frame))
				{
				case 0:
					spr = sprPlayerWithBrain0;
					break;
				case 1:
					spr = sprPlayerWithBrain1;
					break;
				case 2:
					spr = sprPlayerWithBrain0;
					break;
				case 3:
					spr = sprPlayerWithBrain2;
					break;
				}
			}
			else
			{
				switch((int) floor(animation_frame))
				{
				case 0:
					spr = sprPlayer0;
					break;
				case 1:
					spr = sprPlayer1;
					break;
				case 2:
					spr = sprPlayer0;
					break;
				case 3:
					spr = sprPlayer2;
					break;
				}
			}
			spr->SetPosition((float)(int)x,(float)(int)y);
			game->GetWindow()->Draw(*spr);
		}	
		if (!falling)
		{
			sprShadow->SetPosition((float)(int)x,(float)(int)y);
			if (facing)
				sprShadow->FlipX(facing);
			game->GetWindow()->Draw(*sprShadow);
			if (facing)
				sprShadow->FlipX(!facing);
		}
	}
	if (!game->PlayerHasBrain() && brainlessTimer != -1)
	{
		sprBrainBubble->SetPosition((float)(int)x+12,(float)(int)y-32);
		game->GetWindow()->Draw(*sprBrainBubble);
	}
	else if (falling)
	{
		sprExclaim->SetPosition((float)(int)x+12,(float)(int)y-32);
		game->GetWindow()->Draw(*sprExclaim);
	}
	else if (nearSign || nearDoor)
	{
			sprQuestion->SetPosition((float)(int)x+12,(float)(int)y-32);
			game->GetWindow()->Draw(*sprQuestion);
	}
}

cSign *cPlayer::GetSignObject()
{
	if (!readingSign)
		return NULL;
	return (cSign*) signObject;
}

bool cPlayer::IsDead()
{
	return iAmDead;
}