//-----------------------------------------------------------------------------
// Name : CollisionDetection () (Private)
// Desc : Detects and handles collision
//-----------------------------------------------------------------------------
void CGameApp::CollisionDetection()
{
	HDC hdc = m_pBBuffer->getDC();

	// collision detection with the main frame
	for(auto it = m_vGameObjects.begin(); it != m_vGameObjects.end(); ++it)
	{
		CGameObject * pGameObj = it->get();
		Vec2 pos = pGameObj->myPosition;

		if(pGameObj->GetObjectTypeSub() == GOT_BrickNormal || pGameObj->GetObjectTypeSub() == GOT_BrickDouble || pGameObj->GetObjectTypeSub() == GOT_BrickGift)
		{
			BricksExist = true;
		}

		pGameObj->myCollisionSide = CS_None;

		// check collision for ball and player with wall
		if(pGameObj->GetObjectType() == GOT_Ball || pGameObj->GetObjectType() == GOT_Player)
		{
			int dx = (int)pos.x - pGameObj->GetWidth() / 2;
			if( dx < 0 )
			{
				pGameObj->myCollisionSide |= CS_Left;

				if(pGameObj->GetObjectType() == GOT_Ball)
				{
					m_pBall.lock()->myVelocity.x = -m_pBall.lock()->myVelocity.x;
				}

				if(pGameObj->GetObjectType() == GOT_Player)
				{
					pGameObj->myPosition.x = pGameObj->GetWidth()/2;
					if(FollowPlayer == true)
					{
						m_pBall.lock()->myPosition.x = ballPos.x + pGameObj->myPosition.x;
					}
				}
			}

			dx = (int)pos.x - (m_nViewWidth - pGameObj->GetWidth() / 2);
			if( dx > 0 )
			{
				pGameObj->myCollisionSide |= CS_Right;

				if(pGameObj->GetObjectType() == GOT_Ball)
				{
					m_pBall.lock()->myVelocity.x = -m_pBall.lock()->myVelocity.x;
				}

				if(pGameObj->GetObjectType() == GOT_Player)
				{
					pGameObj->myPosition.x = m_nViewWidth - pGameObj->GetWidth() / 2;
					if(FollowPlayer == true)
					{
						m_pBall.lock()->myPosition.x = ballPos.x + pGameObj->myPosition.x;
					}
				}
			}

			int dy = (int)pos.y - pGameObj->GetHeight() / 2;
			if( dy < 0 )
			{
				pGameObj->myCollisionSide |= CS_Top;
				if(pGameObj->GetObjectType() == GOT_Ball)
				{
					m_pBall.lock()->myVelocity.y = -m_pBall.lock()->myVelocity.y;
				}
			}

			dy = (int)pos.y - (m_nViewHeight - pGameObj->GetHeight() / 2);
			if( dy > 0 )
			{
				pGameObj->myCollisionSide |= CS_Bottom;
				if(pGameObj->GetObjectType() == GOT_Ball)
				{
					m_pBall.lock()->myVelocity.y = -m_pBall.lock()->myVelocity.y;
				}
			}

		}

		// check ball collision with game objects
		if(pGameObj->GetObjectType() == GOT_Ball)
			for(auto it2 = m_vGameObjects.begin(); it2 != m_vGameObjects.end(); ++it2)
			{
				CGameObject * pGameObj2 = it2->get();
				Vec2 pos2 = pGameObj2->myPosition;


				if(pGameObj->GetObjectType() == pGameObj2->GetObjectType())
					continue;
				if(pGameObj2->GetObjectType() == GOT_Player || pGameObj2->GetObjectType() == GOT_Brick)
				{

					if(pGameObj2->GetObjectType() == GOT_Player)
					{
						if(pGameObj->myPosition.y > m_nViewHeight - m_pBall.lock()->GetHeight() - m_pPlayer.lock()->GetHeight() + ONE)
						{
							if(!(abs(pos.y - pos2.y) < pGameObj->GetHeight() / 2 + pGameObj2->GetHeight() / 2 && abs(pos.x - pos2.x) < pGameObj->GetWidth() / 2 + pGameObj2->GetWidth() / 2))
							{
								Decrease_Life();
								UnstoppableBall = false;
								StickyBar = false;
								ballPos.x = 0;
								ShrinkBar = false;
								MoveBall = false;
								m_pPlayer.lock()->Normal_Bar();
								SystemParametersInfo(SPI_SETMOUSESPEED, NULL, (void*)10, SPIF_UPDATEINIFILE | SPIF_SENDWININICHANGE );
								if(countLife == NO_LIFE)
								{
									GameOver = true;
								}
							}
						}
					}

					if(abs(pos.y - pos2.y) < pGameObj->GetHeight() / 2 + pGameObj2->GetHeight() / 2 && abs(pos.x - pos2.x) < pGameObj->GetWidth() / 2 + pGameObj2->GetWidth() / 2)
					{		

						if(pGameObj2->GetObjectType() == GOT_Player)
						{
							if(StickyBar == true)
							{
								pGameObj->myVelocity.y = 0;
								pGameObj->myVelocity.x = 0;
								pGameObj->myPosition.y = (int)m_nViewHeight - m_pPlayer.lock()->GetHeight() - m_pBall.lock()->GetHeight() - ONE;
								ballPos.x = pGameObj->myPosition.x - pGameObj2->myPosition.x;
								FollowPlayer = true;
							}
							else
							{
								pGameObj->myVelocity.y = -pGameObj->myVelocity.y;
							}
						}
						else
						{
							if(UnstoppableBall != true)
								if(abs(pos.x - pos2.x) > pGameObj->GetHeight() / 2 + pGameObj2->GetHeight() / 2)
								{// left or right collosion
									pGameObj->myVelocity.x = -pGameObj->myVelocity.x;
								}
								else
								{// top or bottom collision
									pGameObj->myVelocity.y = -pGameObj->myVelocity.y;
								}
						}

						if(pGameObj2->GetObjectTypeSub() == GOT_BrickNormal || pGameObj2->GetObjectTypeSub() == GOT_BrickDouble || pGameObj2->GetObjectTypeSub() == GOT_BrickGift)
						{
							if(pGameObj2->GetObjectTypeSub() == GOT_BrickDouble)
							{						
								int CheckDouble=pGameObj2->DecreaseDouble();
								if(CheckDouble == 1)
								{
									Increase_Score(BRICK_SCORE);
									pGameObj2->ChangeSprite();
								}
								if(CheckDouble == 0)
								{
									Increase_Score(BRICK_SCORE);
									DrawScore(hdc);
									auto pAnimate = std::make_shared<Brick>('k');
									pAnimate->Init(Vec2(pos2.x,pos2.y));
									m_vGameObjectsAnimate.push_back(pAnimate);
									m_vGameObjects.erase(it2);
									break;
								}
							}
							else
							{
								if(pGameObj2->GetObjectTypeSub() == GOT_BrickGift)
								{
									auto pGift = std::make_shared<Gift>(pGameObj2->GetBrickType());
									pGift->Init(Vec2(pos2.x,pos2.y));
									m_vGameObjectsGift.push_back(pGift);
								}
								Increase_Score(BRICK_SCORE);
								DrawScore(hdc);
								auto pAnimate = std::make_shared<Brick>('k');
								pAnimate->Init(Vec2(pos2.x,pos2.y));
								m_vGameObjectsAnimate.push_back(pAnimate);
								m_vGameObjects.erase(it2);
								break;
							}
						}
					}
				}

			}

			// check gift collision with player
			if(pGameObj->GetObjectType() == GOT_Player)
				for(auto it2 = m_vGameObjectsGift.begin(); it2 != m_vGameObjectsGift.end(); ++it2)
				{
					CGameObject * pGameObj2 = it2->get();
					Vec2 pos2 = pGameObj2->myPosition;

					if(abs(pos.y - pos2.y) < pGameObj->GetHeight() / 2 + pGameObj2->GetHeight() / 2 && abs(pos.x - pos2.x) < pGameObj->GetWidth() / 2 + pGameObj2->GetWidth() / 2)
					{
						if(pGameObj2->GetObjectTypeSub() == GOT_Gift100)
						{
							Increase_Score(BRICK_GIFT_SCORE_1);
							DrawScore(hdc);
							m_vGameObjectsGift.erase(it2);
							break;
						}
						if(pGameObj2->GetObjectTypeSub() == GOT_Gift200)
						{
							Increase_Score(BRICK_GIFT_SCORE_2);
							DrawScore(hdc);
							m_vGameObjectsGift.erase(it2);
							break;
						}
						if(pGameObj2->GetObjectTypeSub() == GOT_GiftUpLife)
						{
							Increase_Life();
							DrawLife(hdc);
							m_vGameObjectsGift.erase(it2);
							break;
						}
						if(pGameObj2->GetObjectTypeSub() == GOT_GiftDownLife)
						{
							Decrease_Life2();
							DrawLife(hdc);
							m_vGameObjectsGift.erase(it2);
							break;
						}
						if(pGameObj2->GetObjectTypeSub() == GOT_GiftIncreaseSpeed)
						{
							m_pBall.lock()->Increase_Speed();
							DrawLife(hdc);
							m_vGameObjectsGift.erase(it2);
							break;
						}
						if(pGameObj2->GetObjectTypeSub() == GOT_GiftDecreaseSpeed)
						{
							m_pBall.lock()->Decrease_Speed();
							DrawLife(hdc);
							m_vGameObjectsGift.erase(it2);
							break;
						}
						if(pGameObj2->GetObjectTypeSub() == GOT_GiftUnstoppableBall)
						{
							UnstoppableBall = true;
							m_vGameObjectsGift.erase(it2);
							break;
						}
						if(pGameObj2->GetObjectTypeSub() == GOT_GiftStickyBar)
						{
							StickyBar = true;
							m_vGameObjectsGift.erase(it2);
							break;
						}
						if(pGameObj2->GetObjectTypeSub() == GOT_GiftShrinkBar)
						{
							if(ShrinkBar == false)
							{
								ShrinkBar = true;
								m_pPlayer.lock()->Shrink_Bar();
							}
							m_vGameObjectsGift.erase(it2);
							break;
						}
						if(pGameObj2->GetObjectTypeSub() == GOT_GiftSlowMouse)
						{
							SlowMouse = true;
							break;
						}
					}

					int dy = (int)pos2.y - (m_nViewHeight - pGameObj2->GetHeight() / 2);
					if( dy > 0 )
					{
						m_vGameObjectsGift.erase(it2);
						break;
					}
				}
	}
}
//-----------------------------------------------------------------------------
// Name : FrameAdvance () (Private)
// Desc : Called to signal that we are now rendering the next frame.
//-----------------------------------------------------------------------------
void CGameApp::FrameAdvance()
{
	static TCHAR FrameRate[ 50 ];
	static TCHAR TitleBuffer[ 255 ];

	// Advance the timer
	m_Timer.Tick( 60 );

	// Skip if app is inactive
	if ( !m_bActive ) return;

	// Get / Display the framerate
	if ( m_LastFrameRate != m_Timer.GetFrameRate() )
	{
		m_LastFrameRate = m_Timer.GetFrameRate( FrameRate, 50 );
		sprintf_s( TitleBuffer, _T("Game : %s"), FrameRate );
		SetWindowText( m_hWnd, TitleBuffer );
	} // End if Frame Rate Altered

	if(StartGame == true)
	{

		SetCursor( NULL );

		// Poll & Process input devices
		ProcessInput();

		// Collision detection between game objects
		BricksExist=false;
		CollisionDetection();
		if(BricksExist == false)
		{
			Vec2 brickPos;
			brickPos.x = START_BRICK_POS_X;
			brickPos.y = START_BRICK_POS_Y;

			countBricks = 0;
			countGifts = 0;
			nrBricks = 0;

			// delete objects from previous level
			for(auto it = m_vGameObjects.begin(); it != m_vGameObjects.end(); ++it)
			{
				CGameObject * pGameObj = it->get();

				if(pGameObj->GetObjectTypeSub() == GOT_BrickUnbreakable)
				{
					countBricks++;
				}
			}

			for(int cBricks = 0; cBricks <= countBricks; cBricks++)
			{
				for(auto it2 = m_vGameObjects.begin(); it2 != m_vGameObjects.end(); ++it2)
				{
					CGameObject * pGameObj = it2->get();
					if(pGameObj->GetObjectTypeSub() == GOT_BrickUnbreakable)
					{
						m_vGameObjects.erase(it2);
						break;
					}
				}
			}

			for(auto it = m_vGameObjectsGift.begin(); it != m_vGameObjectsGift.end(); ++it)
			{
				CGameObject * pGameObj = it->get();

				countGifts++;

			}

			for(int cGifts = 0; cGifts <= countGifts; cGifts++)
			{
				for(auto it2 = m_vGameObjectsGift.begin(); it2 != m_vGameObjectsGift.end(); ++it2)
				{
					CGameObject * pGameObj = it2->get();

					m_vGameObjectsGift.erase(it2);
					break;

				}
			}

			// load new objects
			m_pBall.lock()->myVelocity.x = 0;
			m_pBall.lock()->myVelocity.y = 0;
			m_pBall.lock()->myPosition.x = m_pPlayer.lock()->myPosition.x;
			m_pBall.lock()->myPosition.y = m_nViewHeight - m_pBall.lock()->GetHeight() - m_pPlayer.lock()->GetHeight() - ONE;
			FollowPlayer = true;
			UnstoppableBall = false;
			StickyBar = false;
			MoveBall = false;
			SystemParametersInfo(SPI_SETMOUSESPEED, NULL, (void*)10, SPIF_UPDATEINIFILE | SPIF_SENDWININICHANGE );
			ballPos.x = 0;
			if(ShrinkBar == true)
			{
				ShrinkBar = false;
				m_pPlayer.lock()->Normal_Bar();
			}
			nrLevel++;
			level.LoadBricks(nrLevel);
			level.RandomBricks("-ud");

			string::iterator it;
			for(it = level.bricks.begin(); it < level.bricks.end(); it++)
			{
				if(*it == '-')
				{
					continue;
				}
				auto pBrick = std::make_shared<Brick>(*it);
				m_vGameObjects.push_back(pBrick);
			}

			for(auto it = m_vGameObjects.begin(); it != m_vGameObjects.end(); ++it)
			{
				CGameObject * pGameObj = it->get();
				if(pGameObj->GetObjectType() == GOT_Brick)
				{
					for(std::size_t levelbricks = 0; levelbricks < level.bricks.size(); levelbricks++)
					{
						if(level.bricks[nrBricks] == '-')
						{
							brickPos.x += pGameObj->GetWidth();
							if(brickPos.x >= m_nViewWidth - GET_MAX_BRICK_POS_X)
							{
								brickPos.x = START_BRICK_POS_X;
								brickPos.y += pGameObj->GetHeight();
							}
						}
						else
						{
							nrBricks++;
							break; 
						}
						nrBricks++;
					}

					pGameObj->Init(Vec2(brickPos.x, brickPos.y));
					brickPos.x += pGameObj->GetWidth();
					if(brickPos.x >= m_nViewWidth - GET_MAX_BRICK_POS_X)
					{
						brickPos.x = START_BRICK_POS_X;
						brickPos.y += pGameObj->GetHeight();
					}
				}
			}
			if(level.Winner == true)
			{
				LevelChange = false;
			}
			else
			{
				LevelChange = true;
			}
		}

		// Animate the game objects
		AnimateObjects();
	}
	// Drawing the game objects
	DrawObjects();
}