#include "EffectCompiler.h"

EffectCompiler::EffectCompiler(ShaderManager* const manager, const XString& fn) : ShaderProgram(manager, SH_CMP, fn)
{
	D3DXCreateEffectPool(&m_Pool);

	m_MainEffect = new CompiledEffect(this, NULL);
	m_MainEffect->Compile(false);

	Open("");
}

void EffectCompiler::ReleaseSH(void)
{
	delete m_MainEffect;

	m_Effects.Clear();
	
	SAFERELEASE(m_Pool);
}

void EffectCompiler::ReleaseEffect(CompiledEffect* const fx)
{
	ListElement<CompiledEffect> *el = m_Effects.GetElement((DWORD)fx);
	if(el)
		el->Delete();
}

void EffectCompiler::DoRestore(void)
{
	FOREACH(el, m_Effects, CompiledEffect)
	{
		el->GetInfo()->Restore();
	}
}

void EffectCompiler::DoInvalidate(void)
{
	FOREACH(el, m_Effects, CompiledEffect)
	{
		el->GetInfo()->Invalidate();
	}
}

void EffectCompiler::Compile(bool debug)
{
	m_ErrorMsgs = "";

	FOREACH(el, m_Effects, CompiledEffect)
	{
		el->GetInfo()->Compile(debug);
	}

	m_MainEffect->Compile(debug);
}

void EffectCompiler::AddErrorMsgs(const XString& msgs)
{
	m_ErrorMsgs.appand(msgs);
}

CompiledEffect* EffectCompiler::CompileEffect(const bool debug, D3DXMACRO* pDefines)
{
	//try to find effect with same values and literals set
	if(pDefines == NULL)
	{
		m_MainEffect->IncRefCount();
		return m_MainEffect;
	}

	FOREACH(el, m_Effects, CompiledEffect)
	{		
		CompiledEffect* fx = el->GetInfo();

		int i = 0;
		while(true)
		{
			if(fx->GetDefines()[i].Name != pDefines[i].Name || fx->GetDefines()[i].Definition != pDefines[i].Definition)
			{
				break;
			}
			if(fx->GetDefines()[i].Name == NULL && pDefines[i].Name == NULL)
			{
				//the overgiven defines aren't needed anymore
				delete [] pDefines;

				//same define, so just return a reference
				el->GetInfo()->IncRefCount();
				return (CompiledEffect*)el->GetInfo();
			}
			i++;
		}
	}

	CompiledEffect* sh = new CompiledEffect(this, pDefines);
	sh->Compile(debug);
	m_Effects.AddTail(sh, (DWORD)sh);

	return sh;
}