//////////////////////////////////////////////////////
// File: "CGame.cpp"
// Author: Alyssa Dettling (AD)
// Purpose: This file will contain all game functionality
//////////////////////////////////////////////////////

#include "CGame.h"
#include "CGamePlayState.h"
#include "CMainMenuState.h"
#include "CHighScoreState.h"
#include "CCreditsState.h"
#include "CWinGameState.h"
#include "COptionsState.h"
#include <ctime>

CGame::CGame(void)
{
	m_pD3D	= NULL;
	m_pTM	= NULL;
	m_pDI	= NULL;
	m_pFM	= NULL;
	m_pBM = NULL;

	m_fSongVolume = 0.5f;
	m_fSoundVolume = 0.5f;
	m_fPan = 0;

}

CGame::~CGame(void)
{
}

CGame* CGame::GetInstance(void)
{
	static CGame instance;

	return &instance;
}

bool CGame::Initialize(HWND hWnd, HINSTANCE hInstance,
					   int nScreenWidth, int nScreenHeight, bool bIsWindowed)
{
	//	Get pointers to singletons:
	m_pD3D	= CSGD_Direct3D::GetInstance();
	m_pTM	= CSGD_TextureManager::GetInstance();
	m_pDI	= CSGD_DirectInput::GetInstance();
	m_pFM	= CSGD_FModManager::GetInstance();
	m_pAM	= CAnimationManager::GetInstance();
	m_pBM   = CBitmapFontManager::GetInstance();

	m_bIsWindowed = bIsWindowed;
	m_nWidth = nScreenWidth;
	m_nHeight = nScreenHeight;
	//	Call initialize on each wrapper:
	if (!m_pD3D->InitDirect3D(hWnd, nScreenWidth, nScreenHeight, bIsWindowed, false))
		return false;

	if (!m_pTM->InitTextureManager(m_pD3D->GetDirect3DDevice(), m_pD3D->GetSprite()))
		return false;

	
	if (!m_pDI->InitDevices(hWnd, hInstance, false))
		return false;

	if (!m_pFM->InitFModManager(hWnd))
		return false;

	m_pAM->LoadAnimations("Resources/Animation Files/waveAni.dat");
	m_pAM->LoadAnimations("Resources/Animation Files/happyAni.dat");
	m_pAM->LoadAnimations("Resources/Animation Files/sadAni.dat");
	m_pAM->LoadAnimations("Resources/Animation Files/attackAni.dat");
	m_pAM->LoadAnimations("Resources/Animation Files/idleAni.dat");

	//AddState(CGamePlayState::GetInstance());	//AddState(CMainMenuState::GetInstance());
	AddState(CMainMenuState::GetInstance());

	srand((unsigned int)time(0));

	return true;
}

void CGame::Shutdown(void)
{

	//	Clean up current state
	if(m_vCurStates.size() != 0)
		RemoveAllStates( );

	//	Safe way
	if (m_pDI)
	{
		m_pDI->ShutdownDirectInput();
		m_pDI = NULL;
	}

	m_pFM->ShutdownFModManager();

	m_pTM->ShutdownTextureManager();

	m_pD3D->ShutdownDirect3D();
}

bool CGame::Update(void)
{
	DWORD dwCurrentTime = GetTickCount();
	static DWORD dwPreviousTime = GetTickCount();

	float fElapsedTime = (float)(dwCurrentTime - dwPreviousTime) / 1000.0f;
	dwPreviousTime = dwCurrentTime;

	//	1.	Input
	m_pDI->ReadDevices();

	if((m_pDI->GetKey(DIK_LALT) || m_pDI->GetKey(DIK_RALT)))
	{
		if(m_pDI->GetBufferedKey(DIK_RETURN))
		{
			m_bIsWindowed = !m_bIsWindowed;
			m_pD3D->ChangeDisplayParam(m_nWidth,m_nHeight,m_bIsWindowed);

			m_pDI->ReadDevices();
		}	

		if(m_pDI->GetBufferedKey(DIK_F4))
			return false;
	}

	if (!m_vCurStates.empty() && m_vCurStates.back())
		if (!m_vCurStates.back()->Input(fElapsedTime))
			return false;


	//	2.	Update	-	move objects, check collisions, do physics, do AI
	m_pFM->Update();

// 	if(!m_vCurStates.empty())
// 	{
// 		for(unsigned int i=0; i< m_vCurStates.size(); ++i)
// 		{
// 			if(m_vCurStates[i])
// 				m_vCurStates[i]->Update(fElapsedTime);
// 		}
// 	}

	m_pCurState->Update(fElapsedTime);
		

	//	3.	Draw
	if(!m_vCurStates.empty())
	{
		m_pD3D->Clear(0, 0, 0);
		m_pD3D->DeviceBegin();
		m_pD3D->SpriteBegin();

		for(unsigned int i=0; i< m_vCurStates.size(); ++i)
		{
			if(m_vCurStates[i])
				m_vCurStates[i]->Render();
		}

		

		m_pD3D->SpriteEnd();
		m_pD3D->DeviceEnd();
		m_pD3D->Present();
	}
	
	return true;
}

void CGame::AddState(IGameState* pNewState)
{
	if(pNewState)
	{
		m_vCurStates.push_back(pNewState);
		m_pCurState = m_vCurStates.back();
		pNewState->Enter();
	}
}

void CGame::RemoveState()
{
	if(m_vCurStates.size() > 0)
	{
		m_vCurStates.back()->Exit();
		m_vCurStates.pop_back();
		if(m_vCurStates.size())
			m_pCurState = m_vCurStates.back();
	}	
}

void CGame::RemoveAllStates()
{
	for(int i=(int)m_vCurStates.size()-1; i >= 0; --i)
	{
		m_vCurStates[i]->Exit();
	}
	m_vCurStates.clear();
}
