#include "CollisionBox.h"
#include "Game.h"
#include <math.h>
#include "functions.h"
#include "DefenseWall.h"
#include "Player.h"
#include "Fire.h"
#include <OgreEntity.h>
#include <OgreSceneNode.h>
#include "Enemy.h"

using namespace Ogre;
using namespace Engine;

Vector3 CollisionBox::Collide(CollisionBox* aBox)
{
	float mHWidth = mWidth*0.5f;
	float mAHWidth = aBox->mWidth*0.5f;

	float up,down,left,right;

	up = down = left = right = 0;

	float thisLeft = mPosition.x-mHWidth;
	float thisRight = mPosition.x+mHWidth;
	float thisUp = mPosition.y+mHeight; 
	float thisDown = mPosition.y; 

	float hisLeft = aBox->mPosition.x-mAHWidth;
	float hisRight = aBox->mPosition.x+mAHWidth;
	float hisUp = aBox->mPosition.y+aBox->mHeight; 
	float hisDown = aBox->mPosition.y;

	if(thisRight > hisLeft && thisRight < hisRight)
		left = thisRight-hisLeft;
	if(thisLeft < hisRight && thisLeft > hisLeft)
		right = hisRight-thisLeft;

	if(thisUp > hisDown && thisUp < hisUp)
		down = thisUp-hisDown;
	if(thisDown < hisUp && thisDown > hisDown)
		up = hisUp-thisDown;

	float aLeft = fabs(left);
	float aRight = fabs(right);
	float aUp = fabs(up);
	float aDown = fabs(down);

	if(left)
	{
		if(right)
			left = right = 0;
		else if(down)
		{
			if(up)
				down = up = 0;
			else if(aDown < aLeft)
				left = 0;
			else
				down = 0;
		}
		else if(up)
		{
			if(aUp < aLeft)
				left = 0;
			else
				up = 0;
		}
		else
		{
			left = 0;
		}
	}
	else if(right)
	{
		if(down)
		{
			if(up)
				down = up = 0;
			if(aDown < aRight)
				right = 0;
			else
				down = 0;
		}
		else if(up)
		{
			if(aUp < aRight)
				right = 0;
			else
				up = 0;
		}
		else
		{
			right = 0;
		}
	}
	else
	{
		down = up = 0;
	}

	return Vector3(right-left,up-down,0);
}

bool CollisionBox::CheckCollision()
{
	bool collided = false;

	for(int i = 0; i < MAXWALLS; i++)
	{
		if(Game::mDefenseWalls[i]->mActive == 2)
		{
			CollisionBox* defenseWall = (CollisionBox*)Game::mDefenseWalls[i];
			if(mPosition != defenseWall->mPosition)
			{
				Vector3 move = Collide(defenseWall);
				if(move != Vector3::ZERO)
				{
					collided = true;
				}
			}
		}
	}

	for(int i = 0; i < MAXENEMIES; i++)
	{
		CollisionBox* enemy = (CollisionBox*)Game::mEnemies[i];
		if(mPosition != enemy->mPosition && ((Enemy*)enemy)->mActive)
		{
			Vector3 move = Collide(enemy);
			if(move != Vector3::ZERO)
			{
				collided = true;
			}
		}
	}

	CollisionBox* player = (CollisionBox*)Game::mPlayer;
	if(mPosition != player->mPosition)
	{
		Vector3 move = Collide(player);
		if(move != Vector3::ZERO)
		{
			collided = true;
		}
	}

	for(int i = 0; i < Game::mNumLevelBoxes; i++)
	{
		CollisionBox* levelBox = Game::mLevelBoxes[i];
		if(mPosition != levelBox->mPosition)
		{
			Vector3 move = Collide(levelBox);
			if(move != Vector3::ZERO)
			{			
				collided = true;
			}
		}
	}

	return collided;
}

bool CollisionBox::UpdateGroundCollision()
{
	bool collided = false;

	for(int i = 0; i < Game::mNumLevelBoxes; i++)
	{
		CollisionBox* levelBox = Game::mLevelBoxes[i];
		if(mPosition != levelBox->mPosition)
		{
			Vector3 move = Collide(levelBox);
			if(move != Vector3::ZERO)
			{
				mPosition += move;
				collided = true;
				if(move.x)
				{
					mSpeed.x = -mSpeed.x*0.7f;
				}
				if(move.y)
				{
					if(mPosition.y > levelBox->mPosition.y) //we're on top!
					{
						onGround = true;
					}
					else
					{
						mSpeed.y = 0;
					}
				}
			}
		}
	}

	for(int i = 0; i < MAXWALLS; i++)
	{
		if(Game::mDefenseWalls[i]->mActive == 2)
		{
			CollisionBox* defenseWall = (CollisionBox*)Game::mDefenseWalls[i];
			if(mPosition != defenseWall->mPosition)
			{
				Vector3 move = Collide(defenseWall);
				if(move != Vector3::ZERO)
				{
					mPosition += move;
					collided = true;
					if(move.x)
					{
						if(sign(mSpeed.x)==sign(defenseWall->mSpeed.x)) //we're pushing it!
						{
							if(mSpeed.x > defenseWall->mSpeed.x)
								mSpeed.x = defenseWall->mSpeed.x;
						}
						else
						{
							mSpeed.x = -mSpeed.x*0.7f;
						}
					}
					if(move.y)
					{
						if(mPosition.y > defenseWall->mPosition.y) //we're on top!
						{
							onGround = true;
						}
						else
						{
							defenseWall->onGround = true;
							mSpeed.y = 0;
							//if(mType == 4)
							//{
							//	((Enemy*)this)->Die();
							//}
						}
					}
					DefenseWall* wall = ((DefenseWall*)defenseWall);
					if(mType == 2 && wall->mBurningCounter  == 0)
					{
						wall->mBurningCounter = 1;
						wall->mEnt->setMaterialName("DieMauerBurning");
					}
					if(mType == 4)
					{
						if( wall->mBurningCounter > 0 && ((Enemy*)this)->DeathCounter == 0)
						{
							((Enemy*)this)->DeathCounter = 1;
						}
						else
						{
							wall->DoDamage(0.05f*(((Enemy*)this)->mEnemyType+1)*2);
						}
					}
				}
			}
		}
	}

	return collided;
}

bool CollisionBox::UpdateFireCollision()
{
	for (int i = 0; i < MAXBULLETS; i++)
	{
		if(Game::mPlayer->mFireArray->mBullets[i]->mActive)
		{
			CollisionBox* Fire = (CollisionBox*)Game::mPlayer->mFireArray->mBullets[i];
			if(mPosition != Fire->mPosition)
			{
				Vector3 move = Collide(Fire);
				if(move != Vector3::ZERO)
				{
					return true;
				}
			}
			else
			{
				return true;
			}
		}
	}

	return false;
}

bool CollisionBox::CheckBaseCollision()
{
	if(mPosition != Game::mBase->mPosition)
	{
		Vector3 move = Collide(Game::mBase);
		if(move != Vector3::ZERO)
		{
			return true;
		}
	}
	else
	{
		return true;
	}


	return false;
}

bool CollisionBox::UpdateCollision()
{
	bool collided = false;

	for(int i = 0; i < MAXENEMIES; i++)
	{
		CollisionBox* enemy = (CollisionBox*)Game::mEnemies[i];
		if(mPosition != enemy->mPosition && ((Enemy*)enemy)->mActive)
		{
			Vector3 move = Collide(enemy);
			if(move != Vector3::ZERO)
			{
				mPosition += move*0.5f;
				enemy->mPosition -= move*0.5f;
				collided = true;
				if(move.x)
				{
					if(sign(mSpeed.x)==sign(enemy->mSpeed.x)) //we're pushing it!
					{
						if(mSpeed.x > enemy->mSpeed.x)
							mSpeed.x = enemy->mSpeed.x;
					}
					else
					{
						float mSpeedDiff = mSpeed.x-enemy->mSpeed.x;
						mSpeed.x -= mSpeedDiff*0.6f;
						enemy->mSpeed.x += mSpeedDiff*0.6f;
					}
				}
				if(move.y)
				{
					if(mPosition.y > enemy->mPosition.y) //we're on top!
					{
						onGround = true;
						enemy->mSpeed.y = 0;
					}
					else
					{
						enemy->onGround = true;
						mSpeed.y = 0;
					}
				}
				if(mType == 3 && ((Enemy*)enemy)->DeathCounter <= 0)
				{
					((Player*)this)->mHealth -= 12*(((Enemy*)enemy)->mEnemyType+1);
					((Enemy*)enemy)->Die();
				}
			}
		}
	}
	
	CollisionBox* player = (CollisionBox*)Game::mPlayer;
	if(mPosition != player->mPosition)
	{
		Vector3 move = Collide(player);
		if(move != Vector3::ZERO)
		{
			mPosition += move*0.5f;
			player->mPosition -= move*0.5f;
			collided = true;
			if(move.x)
			{
				if(sign(mSpeed.x)==sign(player->mSpeed.x)) //we're pushing it!
				{
					if(mSpeed.x > player->mSpeed.x)
						mSpeed.x = player->mSpeed.x;
				}
				else
				{
					float mSpeedDiff = mSpeed.x-player->mSpeed.x;
					mSpeed.x -= mSpeedDiff*0.6f;
					player->mSpeed.x += mSpeedDiff*0.6f;
				}
			}
			if(move.y)
			{
				if(mPosition.y > player->mPosition.y) //we're on top!
				{
					onGround = true;
					player->mSpeed.y = 0;
				}
				else
				{
					player->onGround = true;
					mSpeed.y = 0;
				}
			}
			if(mType == 4 && ((Enemy*)this)->DeathCounter == 0)
			{
				((Enemy*)this)->Die();
				((Player*)player)->mHealth -= 5;
			}
		}
	}

	if(UpdateGroundCollision())
		collided = true;

	return collided;
}