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

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

//---------------------------
// Defines
//---------------------------
#define GAME_ENGINE (GameEngine::GetSingleton())
#define LEVEL		(Level::GetSingleton())
//---------------------------
// Constructor & Destructor
//---------------------------
Star::Star(int x, int y, Bitmap *bmpBitmapPtr)
	:EntityMaster(x,y,bmpBitmapPtr)
	// bools
	,m_GoesRight(true)
	,m_IsDestroyed(false)
	//ints and doubles
	,m_Width()
	,m_Height()
	,m_EndHeight()
	//others
	,m_BmpBitmapPtr(bmpBitmapPtr)
	,m_HitLevelPtr(nullptr)
	,m_Stage(STAGE::PICKUP)
{
	// nothing to create
	m_Position = DOUBLE2 (x, y);

	// bmp and related
	m_Width = m_BmpBitmapPtr->GetWidth();
	m_Height = m_BmpBitmapPtr->GetHeight();
	m_EndHeight = int(m_Position.y) + m_Height;

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

	// aabb
	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;
}

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

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

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

	switch (m_Stage)
	{
	case Star::STAGE::LOCKED:
		// do nothing
		break;

	case Star::STAGE::POPOUT:
		PopOutTick(deltaTime);
		break;

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

	case Star::STAGE::DESTROYED:
		// do nothing
		break;

	default:
		break;
	}

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

	// update AABB
	UpdateAABB();
}

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

	if (m_Stage == STAGE::POPOUT || m_Stage == STAGE::PICKUP)
		GAME_ENGINE->DrawBitmap(m_BmpBitmapPtr);
}

void Star::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 Star::PickUpTick(double deltaTime)
{
	// direction and speed
	if (m_GoesRight)
		m_Velocity.x += SPEED * deltaTime;
	else 
		m_Velocity.x -= SPEED * deltaTime;

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

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

void Star::UpdateAABB()
{
	RECT2 zero;
	if (m_Stage == STAGE::POPOUT || m_Stage == STAGE::PICKUP)
	{
		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
		m_AABB = zero;
}

void Star::LevelCollisionH()
{
	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 = m_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 Star::LevelCollisionV()
{
	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 = m_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;
		}
	}
}

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

void Star::DrawDebug(MATRIX3X2 matView)
{
	GAME_ENGINE->SetColor(COLOR(255,255,255,150));
	GAME_ENGINE->FillRect(m_AABB);
}

RECT2 Star::GetAABBRect()
{
	RECT2 zero;

	if (m_Stage != STAGE::DESTROYED)
		return m_AABB;
	else 
		return zero;
}


bool Star::IsHit()
{
	return false;
}

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

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

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

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

	if (yVelocity)
		m_Velocity.y = 0;
}

int Star::GetType()
{
	return 4;	// number of star
}


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

int Star::GetMushroomType()
{
	// for mushroom entity only
	return 0;
}



