///////////////////////////
//	File: CSGD_ObjectManager.cpp
//	Author:	Eric Green
//	Purpose: Handles Objects
#include "CSGD_ObjectManager.h"
#include "CSGD_WaveManager.h"
#include "CSGD_TextureManager.h"
#include "CGameClass.h"
#include "CSGD_Dispatcher.h"
#include "CWorld.h"
#include "CSGD_ObjectFactory.h"
#include "CSGD_Direct3D.h"
#include "SGD_Math.h"

#pragma warning (disable:4291)
#define SCREEN_WIDTH 800
#define SCREEN_HEIGHT 600
CSGD_ObjectManager* CSGD_ObjectManager::m_pInstance = 0;



CSGD_ObjectManager::CSGD_ObjectManager(void)
{
}

CSGD_ObjectManager::~CSGD_ObjectManager(void)
{
}

CSGD_ObjectManager* CSGD_ObjectManager::GetInstance()
{
	if(!m_pInstance)
	{
		m_pInstance = new CSGD_ObjectManager;
	}
	return m_pInstance;
}

void CSGD_ObjectManager::AddObject(std::string strID, CBase *pObj)
{
	if(!pObj) return;


	//make sure the object is not already in the registry.
	map<string, CBase*>::iterator mIter = m_Registry.find(strID);
	if(mIter != m_Registry.end())
		return;
	// Add the object to the registry.
	std::pair<string, CBase*> obj;
	obj.first = strID;
	obj.second = pObj;

	m_Registry.insert(obj);

	//addref
	pObj->AddRef();

	m_vObjects.push_back(pObj);
}

void CSGD_ObjectManager::RemoveObject(string strID, CBase* pObj)
{
	if(!pObj) return;


	//make sure the object is not already in the registry.
	map<string, CBase*>::iterator mIter = m_Registry.find(strID);
	if(mIter == m_Registry.end())
		return;

	vector<CBase*>::iterator vIter = m_vObjects.begin();

	while(vIter != m_vObjects.end())
	{
		if((*vIter) == pObj)
		{
			SAFE_RELEASE((*vIter));
			vIter = m_vObjects.erase(vIter);
			m_Registry.erase(mIter);

			return;
		}
		vIter++;
	}
}

void CSGD_ObjectManager::RemoveAllObjects()
{
	//iterator to search through our cevtor
	vector<CBase*>::iterator vIter = m_vObjects.begin();
	while(vIter!=m_vObjects.end())
	{
		CSGD_Dispatcher::GetInstance()->UnregisterClient((*vIter));
		SAFE_RELEASE((*vIter));
		vIter=m_vObjects.erase(vIter);
	}

	m_vObjects.clear();

	m_Registry.clear();
}

void CSGD_ObjectManager::UpdateObjects()
{
	vector<CBase*>::iterator vIter = m_vObjects.begin();
	while(vIter != m_vObjects.end())
	{
		(*vIter)->Update();


		if((*vIter)->GetType() == CBase::eType::OBJECT_MISSILE)
		{
				
				tVector2D v1;
				tVector2D v2;
				tVector2D v3;
				v1.dX = (*vIter)->GetXPos();
				v1.dY = (*vIter)->GetYPos();

				v2.dX = CSGD_ObjectManager::GetInstance()->FindObect("Player")->GetXPos()+16;
				v2.dY = CSGD_ObjectManager::GetInstance()->FindObect("Player")->GetYPos()+16;

				v3.dX = v2.dX - v1.dX;
				v3.dY = v2.dY - v1.dY;
				//newpt = pt1 +k(cos angle, sin angle)


				double Angle = AngleBetweenVectors(v3,v2);

				tVector2D velocity;
				//velocity.dX = cos(Angle) * (10);
				//velocity.dY = sin(Angle) * (10);
				velocity.dX = (v3.dX / Vector2DLength(v3))*3;
				velocity.dY = (v3.dY / Vector2DLength(v3))*3;
				char wtf[128];
				wsprintf(wtf,"Angle:%d",Angle);
				CSGD_Direct3D::GetInstance()->DrawText(wtf,100,10,255,255,255);
				wsprintf(wtf,"Velocity X:%d, Y%d",velocity.dX,velocity.dY);
				CSGD_Direct3D::GetInstance()->DrawText(wtf,100,20,255,255,255);

				if((GetTickCount() - (*vIter)->GetTracking()) > 100)
				{
					(*vIter)->SetVelocity(velocity.dX, velocity.dY);
					(*vIter)->SetTracking(GetTickCount());
				}

			if((GetTickCount() - (*vIter)->GetBirth()) > (*vIter)->GetLifeExpect())
			{
				vIter = m_vObjects.erase(vIter);
				continue;
			}
		}
		if((*vIter)->GetType() == CBase::eType::OBJECT_ENEMY)
		{
			if((GetTickCount() - (*vIter)->GetLastFire()) > 2500)
			{
				CSGD_MessageSystem::GetInstance()->SendMsg(new CCreateBulletMessage(CWorld::eGAME_MESSAGES::eGM_ENEMY_FIRE, (*vIter)));
				(*vIter)->SetLastFire(GetTickCount());
			}
			if((GetTickCount() - (*vIter)->GetBirth()) > (*vIter)->GetLifeExpect())
			{
				vIter = m_vObjects.erase(vIter);
				continue;
			}
		}
		if((*vIter)->GetType() == CBase::eType::OBJECT_MINIBOSS)
		{
			if((GetTickCount() - (*vIter)->GetLastFire()) > 1500)
			{
				if((*vIter)->GetState() == 1)
					CSGD_MessageSystem::GetInstance()->SendMsg(new CCreateBulletMessage(CWorld::eGAME_MESSAGES::eGM_ENEMY_FIRE, (*vIter)));
				if((*vIter)->GetState() == 2)
					CSGD_MessageSystem::GetInstance()->SendMsg(new CCreateBulletMessage(CWorld::eGAME_MESSAGES::eGM_MBOSS_FIRE, (*vIter)));
				if((*vIter)->GetState() == 3)
				{
					CSGD_MessageSystem::GetInstance()->SendMsg(new CCreateBulletMessage(CWorld::eGAME_MESSAGES::eGM_ENEMY_FIRE, (*vIter)));
					CSGD_MessageSystem::GetInstance()->SendMsg(new CCreateBulletMessage(CWorld::eGAME_MESSAGES::eGM_MBOSS_FIRE, (*vIter)));
				}

				(*vIter)->SetLastFire(GetTickCount());
			}
		}
		if((*vIter)->GetType() == CBase::eType::OBJECT_BOSS)
		{
			if((GetTickCount() - (*vIter)->GetLastFire()) > 1000)
			{
				if((*vIter)->GetState() == 1)
					CSGD_MessageSystem::GetInstance()->SendMsg(new CCreateBulletMessage(CWorld::eGAME_MESSAGES::eGM_ENEMY_FIRE, (*vIter)));

				if((*vIter)->GetState() == 2)
					CSGD_MessageSystem::GetInstance()->SendMsg(new CCreateBulletMessage(CWorld::eGAME_MESSAGES::eGM_MBOSS_FIRE, (*vIter)));

				if((*vIter)->GetState() == 3)
				{
					CSGD_MessageSystem::GetInstance()->SendMsg(new CCreateBulletMessage(CWorld::eGAME_MESSAGES::eGM_ENEMY_FIRE, (*vIter)));
					CSGD_MessageSystem::GetInstance()->SendMsg(new CCreateBulletMessage(CWorld::eGAME_MESSAGES::eGM_MBOSS_FIRE, (*vIter)));

				}
				if((*vIter)->GetState() == 4)
				{
					CSGD_MessageSystem::GetInstance()->SendMsg(new CCreateBulletMessage(CWorld::eGAME_MESSAGES::eGM_ENEMY_FIRE, (*vIter)));
					CSGD_MessageSystem::GetInstance()->SendMsg(new CCreateBulletMessage(CWorld::eGAME_MESSAGES::eGM_MBOSS_FIRE, (*vIter)));
					CSGD_MessageSystem::GetInstance()->SendMsg(new CCreateBulletMessage(CWorld::eGAME_MESSAGES::eGM_BOSS_FIRE, (*vIter)));

				}
				if((*vIter)->GetState() == 5)
				{
					CSGD_MessageSystem::GetInstance()->SendMsg(new CCreateBulletMessage(CWorld::eGAME_MESSAGES::eGM_MISSLE_FIRE, (*vIter)));
				}

				(*vIter)->SetLastFire(GetTickCount());
			}
		}
		
	
		if((*vIter)->GetType() == CBase::eType::OBJECT_BULLET)
		{
			if(((*vIter)->GetXPos() < 0 || (*vIter)->GetXPos() > SCREEN_WIDTH+50) 
				|| ((*vIter)->GetYPos() < 0 || (*vIter)->GetYPos() > SCREEN_HEIGHT+50))
			{
				vIter = m_vObjects.erase(vIter);
				continue;
			}
			
		}
		vIter++;
	}
}

void CSGD_ObjectManager::RenderObjects()
{
	vector<CBase*>::iterator vIter = m_vObjects.begin();

	while(vIter!=m_vObjects.end())
	{
		(*vIter)->Render();
		vIter++;
	}
}

CBase* CSGD_ObjectManager::FindObect(std::string strID)
{
	map<string, CBase*>::iterator mIter = m_Registry.find(strID);
	if(mIter == m_Registry.end())
		return 0;

	//return the object pointer
	return (*mIter).second;
	
}

void CSGD_ObjectManager::CheckCollisions()
{
	CSGD_WaveManager* m_pWM = CSGD_WaveManager::GetInstance();
	CWorld* m_pWorld = CWorld::GetInstance();
	vector<CBase*>::iterator vIter = m_vObjects.begin();
	bool Win = 0;
	CSGD_ObjectFactory<string,CBase>* m_pOF = CSGD_ObjectFactory<string,CBase>::GetInstance();
	CSGD_ObjectManager* m_pOM = CSGD_ObjectManager::GetInstance();
	CSGD_TextureManager* m_pTM = CSGD_TextureManager::GetInstance();
	CGameClass* m_pGame = CGameClass::GetInstance();

	while(vIter != m_vObjects.end())
	{
		if((*vIter)->GetType() == CBase::eType::OBJECT_PICKUP)
		{
			Win = 1;
				vector<CBase*>::iterator ColIter = m_vObjects.begin();
			while(ColIter != m_vObjects.end())
			{
				//PICKUP with Player Collision
				if((*ColIter)->GetType() == CBase::eType::OBJECT_PLAYER)
				{
						if((*vIter)->CheckCollision((*ColIter)))
						{

							//PlayPickupSound
							m_pWM->Play(m_pWorld->GetPickupSound());
							if(m_pWorld->GetWeaponLevel() < 3)
								m_pWorld->SetWeaponLevel(m_pWorld->GetWeaponLevel()+1);
							else
								m_pWorld->SetLives(m_pWorld->GetLives()+1);

							vIter = m_vObjects.erase(vIter);
							return;
						}
				}
				if(ColIter != m_vObjects.end())
					ColIter++;
			}
		}
		if((*vIter)->GetType() == CBase::eType::OBJECT_ENEMY)
		{
			Win = 1;
				vector<CBase*>::iterator ColIter = m_vObjects.begin();
			while(ColIter != m_vObjects.end())
			{
				//Enemy with Player Collision
				if((*ColIter)->GetType() == CBase::eType::OBJECT_PLAYER)
				{
					if(!CWorld::GetInstance()->GetGodMode())
						if((*vIter)->CheckCollision((*ColIter)))
						{

							//PlayGameoverSOund
							m_pWM->Play(m_pWorld->GetPlayerHitSound());
							m_pWorld->SetLives(m_pWorld->GetLives()-1);
							if(m_pWorld->GetLives() <=0)
							{
								m_pWorld->SetEndCondition(CWorld::eEnd::END_LOSE);
								//Display GAME OVER NUBSAUCE & return to menu
								m_pGame->GameReset();
								m_pWorld->SetMenuState(CWorld::eMState::MENU_ON);
							}
							return;
						}
				}
				if(ColIter != m_vObjects.end())
					ColIter++;
			}
		}
		
		if((*vIter)->GetType() == CBase::eType::OBJECT_ENEMY)
		{
			Win = 1;
			vector<CBase*>::iterator ColIter = m_vObjects.begin();
			while(ColIter != m_vObjects.end())
			{
				//Enemy with Bullet Collision
				if((*ColIter)->GetType() == CBase::eType::OBJECT_BULLET
					&& (*ColIter)->GetOwner() == CBullet::eOwner::OWNER_PLAYER)
				{
					if((*vIter)->CheckCollision((*ColIter)))
					{
						//playsounds
						m_pWM->Play(m_pWorld->GetEnemyHitSound());
						//remove bullet
						if((*vIter)->GetType() == CBase::eType::OBJECT_ENEMY)
						{
							CSGD_MessageSystem::GetInstance()->SendMsg(new CCreateBulletMessage(CWorld::eGAME_MESSAGES::eGM_ENEMY_FIRE, (*vIter)));
							if(CWorld::GetInstance()->GetWeaponLevel() < 4)
								(*vIter)->SetHealth((*vIter)->GetHealth()-1);
							else
								(*vIter)->SetHealth((*vIter)->GetHealth()-3);
								
							CWorld::GetInstance()->SetScore(CWorld::GetInstance()->GetScore()+10);
						}
						

						//delete enemy if dead
						if((*vIter)->GetType() == CBase::eType::OBJECT_ENEMY && (*vIter)->GetHealth() <= 0)
						{
							CWorld::GetInstance()->SetScore(CWorld::GetInstance()->GetScore()+10);
							if(m_pWorld->GetLevel() > 6)
								CSGD_MessageSystem::GetInstance()->SendMsg(new CCreateEnemyMessage(CWorld::eGAME_MESSAGES::eGM_CREATE_ENEMY));

							vIter = m_vObjects.erase(vIter);
							return;
						}
						ColIter = m_vObjects.erase(ColIter);
						return;

					}
				}
				
				if(ColIter != m_vObjects.end())
					ColIter++;
			}
		
			
			
		}
		if((*vIter)->GetType() == CBase::eType::OBJECT_MINIBOSS)
		{
			Win = 1;
			vector<CBase*>::iterator ColIter = m_vObjects.begin();
			while(ColIter != m_vObjects.end())
			{
				//Enemy with Bullet Collision
				if((*ColIter)->GetType() == CBase::eType::OBJECT_BULLET
					&& (*ColIter)->GetOwner() == CBullet::eOwner::OWNER_PLAYER)
				{
					if((*vIter)->CheckCollision((*ColIter)))
					{
						//playsounds
						m_pWM->Play(m_pWorld->GetEnemyHitSound());
						//remove bullet
						if((*vIter)->GetType() == CBase::eType::OBJECT_MINIBOSS)
						{
							if((*vIter)->GetState() == 1)
								CSGD_MessageSystem::GetInstance()->SendMsg(new CCreateBulletMessage(CWorld::eGAME_MESSAGES::eGM_ENEMY_FIRE, (*vIter)));
							if((*vIter)->GetState() == 2)
								CSGD_MessageSystem::GetInstance()->SendMsg(new CCreateBulletMessage(CWorld::eGAME_MESSAGES::eGM_MBOSS_FIRE, (*vIter)));
							if((*vIter)->GetState() == 3)
							{
								CSGD_MessageSystem::GetInstance()->SendMsg(new CCreateBulletMessage(CWorld::eGAME_MESSAGES::eGM_ENEMY_FIRE, (*vIter)));
								CSGD_MessageSystem::GetInstance()->SendMsg(new CCreateBulletMessage(CWorld::eGAME_MESSAGES::eGM_MBOSS_FIRE, (*vIter)));
							}
							if(CWorld::GetInstance()->GetWeaponLevel() < 4)
								(*vIter)->SetHealth((*vIter)->GetHealth()-1);
							else
								(*vIter)->SetHealth((*vIter)->GetHealth()-3);
								
							CWorld::GetInstance()->SetScore(CWorld::GetInstance()->GetScore()+10);
						}
						//CSGD_MessageSystem::GetInstance()->SendMsg(new CCreateBulletMessage(CWorld::eGAME_MESSAGES::eGM_COLLISION, (*vIter)));
						
						//delete enemy if dead
						if((*vIter)->GetType() == CBase::eType::OBJECT_MINIBOSS && (*vIter)->GetHealth() <= 0)
						{
							CWorld::GetInstance()->SetScore(CWorld::GetInstance()->GetScore()+10);
							CSGD_MessageSystem::GetInstance()->SendMsg(new CCreateBulletMessage(CWorld::eGAME_MESSAGES::eGM_DROP_PICKUP, (*vIter)));
							if(m_pWorld->GetLevel() > 6)
								CSGD_MessageSystem::GetInstance()->SendMsg(new CCreateEnemyMessage(CWorld::eGAME_MESSAGES::eGM_CREATE_MINIBOSS));

							vIter = m_vObjects.erase(vIter);
							return;
						}
						ColIter = m_vObjects.erase(ColIter);
						return;

					}
				}
				
				if(ColIter != m_vObjects.end())
					ColIter++;
			}

		}

		if((*vIter)->GetType() == CBase::eType::OBJECT_BOSS)
		{
			Win = 1;
			vector<CBase*>::iterator ColIter = m_vObjects.begin();
			while(ColIter != m_vObjects.end())
			{
				//Enemy with Bullet Collision
				if((*ColIter)->GetType() == CBase::eType::OBJECT_BULLET
					&& (*ColIter)->GetOwner() == CBullet::eOwner::OWNER_PLAYER)
				{
					if((*vIter)->CheckCollision((*ColIter)))
					{
						//playsounds
						m_pWM->Play(m_pWorld->GetEnemyHitSound());
						//remove bullet
						if((*vIter)->GetType() == CBase::eType::OBJECT_BOSS)
						{
							
							if(CWorld::GetInstance()->GetWeaponLevel() < 4)
								(*vIter)->SetHealth((*vIter)->GetHealth()-1);
							else
								(*vIter)->SetHealth((*vIter)->GetHealth()-3);
								
							CWorld::GetInstance()->SetScore(CWorld::GetInstance()->GetScore()+10);
						}
						//CSGD_MessageSystem::GetInstance()->SendMsg(new CCreateBulletMessage(CWorld::eGAME_MESSAGES::eGM_COLLISION, (*vIter)));
						
						//delete enemy if dead
						if((*vIter)->GetType() == CBase::eType::OBJECT_BOSS && (*vIter)->GetHealth() <= 0)
						{
							CWorld::GetInstance()->SetScore(CWorld::GetInstance()->GetScore()+10);
							CWorld::GetInstance()->SetBossExplode(true);
							CSGD_MessageSystem::GetInstance()->SendMsg(new CCreateBulletMessage(CWorld::eGAME_MESSAGES::eGM_DROP_PICKUP, (*vIter)));
							if(m_pWorld->GetLevel() > 30)
								CSGD_MessageSystem::GetInstance()->SendMsg(new CCreateEnemyMessage(CWorld::eGAME_MESSAGES::eGM_CREATE_BOSS));

							vIter = m_vObjects.erase(vIter);
							return;
						}
						ColIter = m_vObjects.erase(ColIter);
						return;

					}
				}
				
				if(ColIter != m_vObjects.end())
					ColIter++;
			}

		}
		

		if((*vIter)->GetType() == CBase::eType::OBJECT_PLAYER)
		{
			vector<CBase*>::iterator ColIter = m_vObjects.begin();
			while(ColIter != m_vObjects.end())
			{
				//Check for Enemy Bullets hitting Player
				if(((*ColIter)->GetType() == CBase::eType::OBJECT_BULLET 
					|| (*ColIter)->GetType() == CBase::eType::OBJECT_MISSILE)
					&& (*ColIter)->GetOwner() == CBullet::eOwner::OWNER_ENEMY)
				{
					if((*vIter)->CheckCollision((*ColIter)))
					{
						//play ship hit sound
						m_pWM->Play(m_pWorld->GetPlayerHitSound());
						//Send Collision Message with whats getting hit as a param.
						CSGD_MessageSystem::GetInstance()->SendMsg(new CCreateBulletMessage(CWorld::eGAME_MESSAGES::eGM_COLLISION, (*vIter)));
						//reduce ship health
						
						//kill the bullet
						ColIter = m_vObjects.erase(ColIter);
						

					}
				}
				if(ColIter != m_vObjects.end())
					ColIter++;
			}
		}
		if(vIter != m_vObjects.end())
			vIter++;
	}
	//if(!Win)
	//	{
	//		//YOU WIN!
	//		m_pWM->Play(m_pWorld->GetVictorySound());
	//		m_pWorld->SetEndCondition(CWorld::eEnd::END_WIN);
	//		m_pGame->GameReset();
	//		m_pWorld->SetMenuState(CWorld::eMState::MENU_ON);
	//	}

}

