#include "HlslShader.h"
#include "D3DRenderTarget.h"

HlslShader::ScalarVariable::ScalarVariable(ID3D10EffectScalarVariable* variable)
: _variable(variable)
{
}

void HlslShader::ScalarVariable::setValue(int value)
{
    _variable->SetInt(value);
}

void HlslShader::ScalarVariable::setValue(float value)
{
    _variable->SetFloat(value);
}

void HlslShader::ScalarVariable::setValue(bool value)
{
    _variable->SetBool((BOOL)value);
}

void HlslShader::ScalarVariable::setValue(int* value, size_t count)
{
    _variable->SetIntArray(value, 0, (UINT)count);
}

void HlslShader::ScalarVariable::setValue(float* value, size_t count)
{
    _variable->SetFloatArray(value, 0, (UINT)count);
}

void HlslShader::ScalarVariable::setValue(bool* value, size_t count)
{
    _variable->SetBoolArray((BOOL*)value, 0, (UINT)count);
}


HlslShader::VectorVariable::VectorVariable(ID3D10EffectVectorVariable* variable)
: _variable(variable)
{
}

void HlslShader::VectorVariable::setValue(int* value)
{
    _variable->SetIntVector(value);
}

void HlslShader::VectorVariable::setValue(float* value)
{
    _variable->SetFloatVector(value);
}

void HlslShader::VectorVariable::setValue(bool* value)
{
    _variable->SetBoolVector((BOOL*)value);
}

void HlslShader::VectorVariable::setValue(int* value, size_t count)
{
    _variable->SetIntVectorArray(value, 0, (UINT)count);
}

void HlslShader::VectorVariable::setValue(float* value, size_t count)
{
    _variable->SetFloatVectorArray(value, 0, (UINT)count);
}

void HlslShader::VectorVariable::setValue(bool* value, size_t count)
{
    _variable->SetBoolVectorArray((BOOL*)value, 0, (UINT)count);
}


HlslShader::MatrixVariable::MatrixVariable(ID3D10EffectMatrixVariable* variable)
: _variable(variable)
{
}

void HlslShader::MatrixVariable::setValue(float* value)
{
    _variable->SetMatrix(value);
}

void HlslShader::MatrixVariable::setValue(float* value, size_t count)
{
    _variable->SetMatrixArray(value, 0, (UINT)count);
}


HlslShader::ShaderResourceVariable::ShaderResourceVariable(ID3D10EffectShaderResourceVariable* variable)
: _variable(variable)
{
}

void HlslShader::ShaderResourceVariable::setValue(Texture* texture)
{
    if (texture) _variable->SetResource((ID3D10ShaderResourceView*)texture->getResourceHandle());
}

void HlslShader::ShaderResourceVariable::setValue(RenderTarget* renderTarget)
{
    if (D3DRenderTarget* d3dRT = dynamic_cast<D3DRenderTarget*>(renderTarget)) {
        _variable->SetResource(d3dRT->getShaderResourceView());
    }
}

void HlslShader::ShaderResourceVariable::setValue(void* resourceHandle)
{
    _variable->SetResource((ID3D10ShaderResourceView*)resourceHandle);
}



HlslShader::HlslShader(ID3D10Effect* effect, ID3D10EffectTechnique* technique, ID3D10InputLayout* layout)
: Shader(), _effect(effect), _technique(technique), _layout(layout)
{
}


HlslShader::ScalarVariable* HlslShader::createScalarVariable(const char* variableName)
{
    ID3D10EffectScalarVariable* hlslVariable = _effect->GetVariableByName(variableName)->AsScalar();

    if (hlslVariable->IsValid()) {
        ScalarVariable* variable = new ScalarVariable(hlslVariable);
        return variable;
    }
    else {
        return NULL;
    }
}

HlslShader::VectorVariable* HlslShader::createVectorVariable(const char* variableName)
{
    ID3D10EffectVectorVariable* hlslVariable = _effect->GetVariableByName(variableName)->AsVector();

    if (hlslVariable->IsValid()) {
        VectorVariable* variable = new VectorVariable(hlslVariable);
        return variable;
    }
    else {
        return NULL;
    }
}

HlslShader::MatrixVariable* HlslShader::createMatrixVariable(const char* variableName)
{
    ID3D10EffectMatrixVariable* hlslVariable = _effect->GetVariableByName(variableName)->AsMatrix();

    if (hlslVariable->IsValid()) {
        MatrixVariable* variable = new MatrixVariable(hlslVariable);
        return variable;
    }
    else {
        return NULL;
    }
}

HlslShader::ShaderResourceVariable* HlslShader::createShaderResourceVariable(const char* variableName)
{
    ID3D10EffectShaderResourceVariable* hlslVariable = _effect->GetVariableByName(variableName)->AsShaderResource();

    if (hlslVariable->IsValid()) {
        ShaderResourceVariable* variable = new ShaderResourceVariable(hlslVariable);
        return variable;
    }
    else {
        return NULL;
    }
}


ID3D10Effect* HlslShader::getEffect()
{
    return _effect;
}

ID3D10EffectTechnique* HlslShader::getTechnique()
{
    return _technique;
}

ID3D10InputLayout* HlslShader::getLayout()
{
    return _layout;
}