#include "RuScaleformDriver_D3D9.h"

#include "../Rune/Direct3D/Engine/RuEngineD3D.h"

#pragma managed(push, off)

// ************************************************************************************************************************************************************

ruRTTI_DEFINE_SUBCLASS(CRuScaleformDriver_D3D9, IRuScaleformDriver)
ruHEAP_DEFINE_SUBCLASS(CRuScaleformDriver_D3D9, "CRuScaleformDriver_D3D9", "IRuScaleformDriver")
ruCLASSGUID_DEFINE(CRuScaleformDriver_D3D9, 0x9D1AAC3F, 0xE66C4eed, 0xB2F67110, 0x4CDD5E19)

// ************************************************************************************************************************************************************

CRuScaleformDriver_D3D9::CRuScaleformDriver_D3D9()
{
	// Create a GFx renderer
	m_renderer = *GRendererD3D9::CreateRenderer();
	m_renderConfig = *new GFxRenderConfig(m_renderer);

	// Associate the GFx renderer with the GFxLoader
	m_loader.SetRenderConfig(m_renderConfig);
}

CRuScaleformDriver_D3D9::~CRuScaleformDriver_D3D9()
{
	// Unregister handlers
	m_engine->Event_DeviceReset().UnregisterHandler(this->GetGUID());
	m_engine->Event_DeviceRestore().UnregisterHandler(this->GetGUID());
}

BOOL CRuScaleformDriver_D3D9::AttachToEngine(IRuEngine *engine)
{
	if(engine->GetType() == CRuEngineD3D::Type())
	{
		// Store reference to engine
		m_engine = engine;

		// Register handlers
		m_engine->Event_DeviceReset().RegisterHandler(this->GetGUID(), boost::bind(&CRuScaleformDriver_D3D9::DeviceResetHandler, this, _1));
		m_engine->Event_DeviceRestore().RegisterHandler(this->GetGUID(), boost::bind(&CRuScaleformDriver_D3D9::DeviceRestoreHandler, this, _1));

		// Get D3D9 device from engine
		IDirect3DDevice9 *d3dDevice = static_cast<CRuEngineD3D *>(m_engine)->GetD3DDevice();

		// Get current present parameters from primary swap chain
		IRuSwapChain *swapChain = m_engine->GetPrimarySwapChain();
		D3DPRESENT_PARAMETERS &presentParams = static_cast<CRuSwapChainD3D *>(swapChain)->PresentParameters();

		// Get handle to primary window from engine
		HWND hWnd = static_cast<CRuEngineD3D *>(m_engine)->GetPrimaryWindow();

		// Set dependent video mode for GFx
		m_renderer->SetDependentVideoMode(d3dDevice, &presentParams, GRendererD3D9::VMConfig_NoSceneCalls, hWnd);

		return TRUE;
	}

	return FALSE;
}

BOOL CRuScaleformDriver_D3D9::ClearEngineStates()
{
	if(m_engine)
	{
		m_engine->ClearStateCache();
		return TRUE;
	}

	return FALSE;
}

GFxLoader *CRuScaleformDriver_D3D9::GetLoader()
{
	return &m_loader;
}

GRenderer *CRuScaleformDriver_D3D9::GetRenderer()
{
	return m_renderer;
}

CRuRectangle CRuScaleformDriver_D3D9::GetViewportRect()
{
	CRuRectangle viewportRect(0, 0, static_cast<REAL>(m_engine->GetPrimarySwapChain()->GetWidth()), static_cast<REAL>(m_engine->GetPrimarySwapChain()->GetHeight()));
	return viewportRect;
}

BOOL CRuScaleformDriver_D3D9::DeviceResetHandler(RuEventArgs *eventArgs)
{
	m_renderer->ResetVideoMode();
	return TRUE;
}

BOOL CRuScaleformDriver_D3D9::DeviceRestoreHandler(RuEventArgs *eventArgs)
{
	// Get D3D9 device from engine
	IDirect3DDevice9 *d3dDevice = static_cast<CRuEngineD3D *>(m_engine)->GetD3DDevice();

	// Get current present parameters from primary swap chain
	IRuSwapChain *swapChain = m_engine->GetPrimarySwapChain();
	D3DPRESENT_PARAMETERS &presentParams = static_cast<CRuSwapChainD3D *>(swapChain)->PresentParameters();

	// Get handle to primary window from engine
	HWND hWnd = static_cast<CRuEngineD3D *>(m_engine)->GetPrimaryWindow();

	// Set dependent video mode for GFx
	m_renderer->SetDependentVideoMode(d3dDevice, &presentParams, GRendererD3D9::VMConfig_NoSceneCalls, hWnd);

	return TRUE;
}

// ************************************************************************************************************************************************************

#pragma managed(pop)
