#include "dxstdafx.h"
#include "PostProcFXFilesManager.h"
#include "PPEffectsCommon.h"

// Global variables (more like FX paths)
WCHAR sPostProcessFolder[100] = L"./FXFiles/PostProcess/\0";

#pragma once


//------------------------------------------------------------------------------------------
// Constructor
// Prepares the filename list
//------------------------------------------------------------------------------------------
PostProcFXFilesManager::PostProcFXFilesManager()
{
	ClearEverything();
}


//--------------------------------------------------------------------------------------
// Destructor
//--------------------------------------------------------------------------------------
PostProcFXFilesManager::~PostProcFXFilesManager()
{
	ClearEverything();
}


//--------------------------------------------------------------------------------------
// Clear a list<WCHAR*>
//--------------------------------------------------------------------------------------
void PostProcFXFilesManager::ClearFilenameList()
{
	// Deleting the real time effect file list
	list<wstring*>::const_iterator FilenameIterator;
	for(FilenameIterator=m_lstPostProcFXFilestList.begin(); FilenameIterator!=m_lstPostProcFXFilestList.end(); ++FilenameIterator)
	{
		if(*FilenameIterator)
			delete (*FilenameIterator);
	}
	m_lstPostProcFXFilestList.clear();
}


//--------------------------------------------------------------------------------------
// Clear a list<PPEffectsCommon*>
//--------------------------------------------------------------------------------------
void PostProcFXFilesManager::ClearCompiledFXList()
{
	// Deleting the real time effect file list
	list<PPEffectsCommon*>::const_iterator FXIterator;
	for(FXIterator=m_lstCompiledPostProcFX.begin(); FXIterator!=m_lstCompiledPostProcFX.end(); ++FXIterator)
	{
		if(*FXIterator)
		{
			PPEffectsCommon * pEffect = (PPEffectsCommon * )(*FXIterator);
			delete pEffect;
		}
	}
	m_lstCompiledPostProcFX.clear();
}


//--------------------------------------------------------------------------------------
// Clear everything
//--------------------------------------------------------------------------------------
void PostProcFXFilesManager::ClearEverything()
{
	// Clearing the lists
	ClearFilenameList();
	ClearCompiledFXList();
}


//--------------------------------------------------------------------------------------
// Retrieve the postprocess .fx filenames
//--------------------------------------------------------------------------------------
void PostProcFXFilesManager::ListAvailablePostProcEffects(const int nNbAvailableRTs)
{
	// We'll use the Windows API to browse the directory using a file finder
	WIN32_FIND_DATA FindFileData;
	HANDLE hFind = INVALID_HANDLE_VALUE;

	// We first measure the length of the post process folder relative path
	int nPPFolderPathLength = (int)(wcslen(sPostProcessFolder));

	// We construct a filter that will enable searching only fx files in the postprocess directory
	WCHAR sFXFilter[5] = L"*.fx";	// We'll search all *.fx files in the folder
	WCHAR sFullFilter[100];
	wcsncpy_s(sFullFilter, _countof(sFullFilter), sPostProcessFolder, nPPFolderPathLength+1);	// Add 1 to force "\0" at the end of the copy
	wcscat_s(sFullFilter, _countof(sFullFilter), sFXFilter);

	// Then try to get a file finder handle that will use our filter
	hFind = FindFirstFile(sFullFilter, &FindFileData);
	BOOL bFoundANewFile = TRUE;

	// Now trying to compile the effect file
	// If compilation is successful the effect is listed
	// Then we try to do the same on other files corresponding our criteria in the same folder
	while( (hFind != INVALID_HANDLE_VALUE) && (bFoundANewFile==TRUE) )
	{
		// Reconstruct the *.fx file relative path
		WCHAR pFXFileRelativePath[260];
		wcsncpy_s(pFXFileRelativePath, _countof(sFullFilter), sPostProcessFolder, nPPFolderPathLength+1);
		wcscat_s(pFXFileRelativePath, _countof(sFullFilter), FindFileData.cFileName);

		// Compiling the effect
		PPEffectsCommon * pNewEffect = new PPEffectsCommon(pFXFileRelativePath, nNbAvailableRTs);
		if(pNewEffect->getEffect())
		{
			// Success? Yes!
			m_lstCompiledPostProcFX.push_back(pNewEffect);	// Save the compiled effect on the list

			wstring * pFileName = new wstring();			// Create a new WCHAR string the same size as the filename
			pFileName->append(FindFileData.cFileName);		// And put the filename in it
			m_lstPostProcFXFilestList.push_back(pFileName);	// And push it to the list by the back
		}
		
		// Trying to find a new file now
		bFoundANewFile = FindNextFile(hFind, &FindFileData);
	}
	
	// We close the file finder handle
	if(hFind != INVALID_HANDLE_VALUE) FindClose(hFind);
}


//--------------------------------------------------------------------------------------
// Fill a DXUT list box with the effect list
//--------------------------------------------------------------------------------------
void PostProcFXFilesManager::FillListBox(CDXUTListBox * pListBox) const
{
	// Getting iterators on the filename list and the compiled effects
	list<wstring*>::const_iterator FilenameIterator;
	list<PPEffectsCommon*>::const_iterator FXIterator;

	// Fill the list with PPEffectsCommon*
	for(FilenameIterator=m_lstPostProcFXFilestList.begin(), FXIterator=m_lstCompiledPostProcFX.begin();	FilenameIterator!=m_lstPostProcFXFilestList.end(); ++FilenameIterator, ++FXIterator)
		pListBox->AddItem((*FilenameIterator)->c_str(), (*FXIterator));
}
	

//--------------------------------------------------------------------------------------
// OnResetDevice
//--------------------------------------------------------------------------------------
HRESULT PostProcFXFilesManager::OnResetDevice(const int nWidth, const int nHeight) const
{
	HRESULT hr;
	
	// Reseting all the effects on the list
	list<PPEffectsCommon*>::const_iterator EffectIterator;
	for(EffectIterator=m_lstCompiledPostProcFX.begin(); EffectIterator!=m_lstCompiledPostProcFX.end(); ++EffectIterator)
		V_RETURN( (*EffectIterator)->OnResetDevice(nWidth, nHeight) );	// Call the effect OnReset routine

	return S_OK;
}


//--------------------------------------------------------------------------------------
// OnLostDevice
//--------------------------------------------------------------------------------------
void PostProcFXFilesManager::OnLostDevice() const
{
	// Call the effects OnLost routine
	list<PPEffectsCommon*>::const_iterator EffectIterator;
	for(EffectIterator=m_lstCompiledPostProcFX.begin(); EffectIterator!=m_lstCompiledPostProcFX.end(); ++EffectIterator)
		(*EffectIterator)->OnLostDevice();
}