//-----------------------------------------------------
// Name, first name: Hoet, Guntran
// Group: 1DAE3
//-----------------------------------------------------

//---------------------------
// Includes
//---------------------------
#include "Mushroom.h"

//---------------------------
// Defines
//---------------------------
#define GAME_ENGINE (GameEngine::GetSingleton())
#define MARIO		(Mario::GetSingleton())
#define LEVEL		(Level::GetSingleton())
//---------------------------
// Constructor & Destructor
//---------------------------
Mushroom::Mushroom(int x, int y, Bitmap *bmpBitmapPtr, int type)
	:EntityMaster(x, y, bmpBitmapPtr)
	// bools
	,m_GoesRight(true)
	,m_IsDestroyed(false)
	// int - doubles
	,m_Width()
	,m_Height()
	,m_EndHeight()
	,m_MushroomType(type)
	//other
	,m_BmpMushroomPtr(nullptr)
	,m_Stage(STAGE::POPOUT)
	,m_HitLevelPtr(nullptr)
{
	// position
	m_Position = DOUBLE2 (x,y);

	// bitmap
	m_BmpMushroomPtr = bmpBitmapPtr;

	// type
	if (type == 0)
		m_Type = TYPE::NORMAL;
	if (type == 1)
		m_Type = TYPE::UP;

	// hitr
	m_HitLevelPtr = LEVEL->GetHitRegion();

	// datamembers
	m_Width = m_BmpMushroomPtr->GetWidth() / NR_STEPS;
	m_Height = m_BmpMushroomPtr->GetHeight();
	m_EndHeight = int(m_Position.y - m_Height);		// altitude to rise to, before going to pickup state

	// aabb rect
	m_AABB.top = m_Position.y;
	m_AABB.bottom = m_AABB.top + m_Height;
	m_AABB.left = m_Position.x;
	m_AABB.right = m_AABB.left + m_Width;

	// clip rect
	m_Clip.top = 0;
	m_Clip.bottom = m_Clip.top + m_Height;
	m_Clip.left = m_Width * m_MushroomType;
	m_Clip.right = m_Clip.left + m_Width;
}

Mushroom::~Mushroom()
{
	// nothing to destroy
}

//---------------------------
// Methods - Member functions
//---------------------------

void Mushroom::Create()
{
	// not needed...
}

void Mushroom::Tick(double deltaTime)
{
	m_Velocity.x = 0;

	switch (m_Stage)
	{
	case Mushroom::STAGE::LOCKED:
		LockedTick(deltaTime);
		break;

	case Mushroom::STAGE::POPOUT:
		PopoutTick(deltaTime);
		break;

	case Mushroom::STAGE::PICKUP:
		PickUpTick(deltaTime);
		break;

	case Mushroom::STAGE::DESTROYED:
		DestroyedTick(deltaTime);
		break;
	}

	// gravity
	if (m_Stage == (STAGE)2)
		m_Velocity.y += FORCE_GRAVITY * deltaTime;
	// resulting pos
	m_Position += m_Velocity * deltaTime;

	// aabb rect update
	if (m_Stage == STAGE::PICKUP || m_Stage == STAGE::POPOUT)
	{
		m_AABB.top = m_Position.y;
		m_AABB.bottom = m_AABB.top + m_Height;
		m_AABB.left = m_Position.x;
		m_AABB.right = m_AABB.left + m_Width;
	}
	else
	{
		RECT2 zero;
		m_AABB = zero;
	}
}

void Mushroom::Paint(MATRIX3X2 matView)
{
	MATRIX3X2 matTranslate, matTransform;
	matTranslate.SetAsTranslate(m_Position);
	matTransform = matTranslate * matView;
	GAME_ENGINE->SetTransformMatrix(matTransform);

	switch (m_Stage)
	{
	case Mushroom::STAGE::LOCKED:
		//GAME_ENGINE->DrawBitmap(m_BmpMushroomPtr);		// draw none in lock state
		break;

	case Mushroom::STAGE::POPOUT:
		GAME_ENGINE->DrawBitmap(m_BmpMushroomPtr,0,0,m_Clip);
		break;

	case Mushroom::STAGE::PICKUP:
		GAME_ENGINE->DrawBitmap(m_BmpMushroomPtr,0,0,m_Clip);
		break;

	case Mushroom::STAGE::DESTROYED:
		// dont draw
		break;
	}
}

void Mushroom::LockedTick(double deltaTime)
{
	// nothing just wait.
}	  

void Mushroom::PopoutTick(double deltaTime)
{
	if (m_Position.y >= m_EndHeight)
		m_Position.y -= POP_SPEED_GENERAL * deltaTime;			

	if(m_Position.y < m_EndHeight)
	{
		m_Velocity.y = 0;
		m_Stage = STAGE::PICKUP;
	}
}

void Mushroom::PickUpTick(double deltaTime)
{
	// direction and speed
	if (m_GoesRight)
		m_Velocity.x += SPEED * deltaTime;
	else 
		m_Velocity.x -= SPEED * deltaTime;

	// level collision
	LevelCollisionH(m_HitLevelPtr);
	LevelCollisionV(m_HitLevelPtr);

	// check if fallen to low
	if (m_Position.y >= LEVEL->CRUSH_ALTITUDE)
		m_Stage = (STAGE)3;	// set to destroyed stage
}

void Mushroom::DestroyedTick(double deltaTime)
{
	m_IsDestroyed = true;
}

void Mushroom::LevelCollisionH(HitRegion *hitLevelPtr)
{
	DOUBLE2 startPos (m_Position.x, (m_Position.y+m_Height/2));
	DOUBLE2 vector (m_Width, 0);
	const int nrRaycasts = 1;

	HIT hitArr[nrRaycasts]={};
	int nrHits = hitLevelPtr->Raycast(startPos, vector, hitArr, nrRaycasts, 0);

	if (nrHits > 0)
	{
		double lambda = hitArr[0].lambda;

		if (lambda > .5)
		{
			m_GoesRight = false;	// go left
			double depth = (1-lambda) * vector.Length();
			m_Position.x -= depth;
		}
		if (lambda <= .5)
		{
			m_GoesRight = true;		// go right
			double depth = lambda * vector.Length();
			m_Position.x += depth;
		}
	}
}

void Mushroom::LevelCollisionV(HitRegion *hitLevelPtr)
{
	DOUBLE2 startPos (m_Position.x+(m_Width/2), m_Position.y);
	DOUBLE2 vector (0, m_Height);
	const int nrRaycasts = 1;

	HIT hitArr[nrRaycasts]={};
	int nrHits = hitLevelPtr->Raycast(startPos, vector, hitArr, nrRaycasts, 0);

	if (nrHits > 0)
	{
		double lambda = hitArr[0].lambda;
		m_Velocity.y = 0;

		if (lambda > .5)
		{
			double depth = (1-lambda) * vector.Length();
			m_Position.y -= depth;
		}
		if (lambda <= .5)
		{
			double depth = lambda * vector.Length();
			m_Position.y += depth;
		}
	}
}

//void Mushroom::LockedPaint(MATRIX3X2 matView)
//{
//
//}
//
//void Mushroom::PopoutPaint(MATRIX3X2 matView)
//{
//
//}
//
//void Mushroom::PickUpPaint(MATRIX3X2 matView)
//{
//	MATRIX3X2 matTranslate, matTransform;
//	matTranslate.SetAsTranslate(m_Position);
//	matTransform = matTranslate * matView;
//}
//
//void Mushroom::DestroyedPaint(MATRIX3X2 matView)
//{
//
//}

DOUBLE2 Mushroom::GetPos()
{
	return m_Position;
}

RECT2 Mushroom::GetAABBRect()
{
	return m_AABB;
}

bool Mushroom::IsHit()
{
	m_Stage = STAGE::DESTROYED;
	return true;
}

int Mushroom::ReturnReward()
{
	return 1000;
}

int Mushroom::GetStage()
{
	switch (m_Stage)
	{
	case Mushroom::STAGE::LOCKED:
		return 0;
	case Mushroom::STAGE::POPOUT:
		return 1;
	case Mushroom::STAGE::PICKUP:
		return 2;
	case Mushroom::STAGE::DESTROYED:
		return 3;
	default:
		return -1;
	}
}

void Mushroom::DrawDebug(MATRIX3X2 matView)
{
	// paint debug stuff here!
	GAME_ENGINE->SetColor(COLOR(255,0,255,150));
	GAME_ENGINE->FillRect(m_AABB);
}

void Mushroom::Delete()
{
	// nothing
}

void Mushroom::Move(DOUBLE2 dir)
{
	m_Position += dir;
}

void Mushroom::ZeroVelocity(bool xVelocity, bool yVelocity)
{
	if (xVelocity)
		m_Velocity.x = 0;

	if (yVelocity)
		m_Velocity.y = 0;
}

int Mushroom::GetType()
{
	return EntityMaster::TYPE_MUSHROOM;
}

void Mushroom::SetStage(int stage)
{
	m_Stage = (STAGE)stage;
}

int Mushroom::GetMushroomType()
{
	return m_MushroomType;
}







