#pragma once

#include "DLLInterface.h"
#include "ShaderProgram.h"
#include "DXVector4.h"
#include "DXTexture.h"

#define RENDERFX(shfx,todo)									\
{															\
	UINT cPasses;											\
	shfx->GetShader()->Begin(&cPasses,0);					\
	for (UINT iPass = 0; iPass < cPasses; iPass++)			\
    {														\
		shfx->GetShader()->BeginPass(iPass);				\
		todo												\
		shfx->GetShader()->EndPass();		\
	}								\
	shfx->GetShader()->End();		\
}		

class DXFUNCTIONS_API ShaderEffect : public ShaderProgram
{
	friend ShaderManager;

protected:

	LPD3DXEFFECT m_Shader;

	ShaderEffect(ShaderManager* const manager, const XString& fn);
	~ShaderEffect(void) { ReleaseSH(); }
	void ReleaseSH(void);

	virtual void DoRestore(void);
	virtual void DoInvalidate(void);

	void OpenBin(void);
	void CreatePrecompiledCode(void);

public:

	virtual void Compile(bool debug = false);
	XString GetDisassembly(void);

	virtual void Open(const XString& fn);

	LPD3DXEFFECT GetShader(void){return m_Shader;}

	unsigned GetSamplerIndex(XString sampler);

	D3DXHANDLE GetHandle(const char* name) { return m_Shader->GetParameterByName(NULL, name); }
	void SetFloat(const D3DXHANDLE h, const float value) { m_Shader->SetFloat(h, value); }
	void SetVector(const D3DXHANDLE h, const DXVector4& v) { m_Shader->SetVector(h, (D3DXVECTOR4*)&v);}
	void SetFloatArray(const D3DXHANDLE h, const float* v, const int count) { m_Shader->SetFloatArray(h, v, count);}
	void SetTexture(const D3DXHANDLE h, const DXSurface* const tex) { m_Shader->SetTexture(h, tex ? tex->GetSurface() : NULL); }
	void SetMatrix(const D3DXHANDLE h, const DXMatrix& mat) { m_Shader->SetMatrix(h, (D3DXMATRIX*)&mat);}
	void SetInt(const D3DXHANDLE h, const int v) {m_Shader->SetInt(h, v); }
	void SetValue(const D3DXHANDLE h, const void* value, const unsigned bytecount) { m_Shader->SetValue(h, value, bytecount); }

	int Begin(void) {UINT cPasses;	m_Shader->Begin(&cPasses,0); return cPasses;}
	void End(void) {m_Shader->End();}
	void BeginPass(const int pass) {m_Shader->BeginPass(pass);}
	void EndPass(void) {m_Shader->EndPass();}

	void SetTechnique(const XString& tech);
};