#include "shader_manager_class.h"

shader_manager_class::shader_manager_class()
{
    texture_shader_ = 0;
    normal_map_shader_ = 0;
    multitexture_shader_ = 0;
    translate_shader_ = 0;
    alpha_map_shader_ = 0;
    spec_map_shader_ = 0;
    transparent_shader_ = 0;
    light_shader_ = 0;
    light_map_shader_ = 0;
    refraction_shader_ = 0;
    water_shader_ = 0;
    cel_shading_shader_ = 0;
    sunlight_shader_ = 0;
    skybox_shader_ = 0;
    refraction_shader_ = 0;
    depth_shader_ = 0;
}

shader_manager_class::shader_manager_class(const shader_manager_class& other)
{
}

shader_manager_class::~shader_manager_class()
{
}

bool shader_manager_class::initialize(ID3D11Device* device, HWND hwnd)
{
    LOG_INIT("Initializing shader_manager_class");

    bool result;

    // Create and initialize the texture shader object.
    texture_shader_ = new texture_shader_class;
    result = texture_shader_->initialize(device, hwnd);
    if (!result)
    {
        LOG_ERROR("Error initializing texture_shader_class");
        R_FALSE
    }

    // Create and initialize the normal map shader object.
    normal_map_shader_ = new normal_map_shader_class;
    result = normal_map_shader_->initialize(device, hwnd);
    if (!result)
    {
        LOG_ERROR("Error initializing normal_map_shader_class");
        R_FALSE
    }

    // Create and initialize the multitexture shader object.
    multitexture_shader_ = new multi_texture_shader_class;
    result = multitexture_shader_->initialize(device, hwnd);
    if (!result)
    {
        LOG_ERROR("Error initializing multi_texture_shader_class");
        R_FALSE
    }

    // Create and initialize the translate shader object.
    translate_shader_ = new translate_shader_class;
    result = translate_shader_->initialize(device, hwnd);
    if (!result)
    {
        LOG_ERROR("Error initializing translate_shader_class");
        R_FALSE
    }

    // Create and initialize the alpha map shader object.
    alpha_map_shader_ = new alpha_map_shader_class;
    result = alpha_map_shader_->initialize(device, hwnd);
    if (!result)
    {
        LOG_ERROR("Error initializing alpha_map_shader_class");
        R_FALSE
    }

    // Create and initialize the specular map shader object.
    spec_map_shader_ = new spec_map_shader_class;
    result = spec_map_shader_->initialize(device, hwnd);
    if (!result)
    {
        LOG_ERROR("Error initializing spec_map_shader_class");
        R_FALSE
    }

    // Create and initialize the transparent shader object.
    transparent_shader_ = new transparent_shader_class;
    result = transparent_shader_->initialize(device, hwnd);
    if (!result)
    {
        LOG_ERROR("Error initializing transparent_shader_class");
        R_FALSE
    }

    // Create and initialize the light shader object.
    light_shader_ = new light_shader_class;
    result = light_shader_->initialize(device, hwnd);
    if (!result)
    {
        LOG_ERROR("Error initializing light_shader_class");
        R_FALSE
    }

    // Create and initialize the light map shader object.
    light_map_shader_ = new light_map_shader_class;
    result = light_map_shader_->initialize(device, hwnd);
    if (!result)
    {
        LOG_ERROR("Error initializing light_map_shader_class");
        R_FALSE
    }

    // Create and initialize the refraction shader object.
    refraction_shader_ = new refraction_shader_class;
    result = refraction_shader_->initialize(device, hwnd);
    if (!result)
    {
        R_FALSE
    }

    // Create and initialize the water shader object.
    water_shader_ = new water_shader_class;
    result = water_shader_->initialize(device, hwnd);
    if (!result)
    {
        R_FALSE
    }

    cel_shading_shader_ = new celshade_class;
    result = cel_shading_shader_->initialize(device, hwnd);
    if (!result)
    {
        R_FALSE
    }

	sunlight_shader_ = new sunlight_shader_class;
	result = sunlight_shader_->initialize(device, hwnd);
	if (!result)
	{
		R_FALSE
	}

    skybox_shader_ = new skybox_shader_class;
    result = skybox_shader_->Initialize(device, hwnd);
    if (!result)
    {
        LOG_ERROR("Error initializing skybox_shader_class");
        R_FALSE
    }

    depth_shader_ = new depth_shader_class;
    result = depth_shader_->initialize(device, hwnd);
    if (!result)
    {
        LOG_ERROR("Error initializing depth_shader_class");
        R_FALSE
    }

    LOG_INIT("shader_manager_class initialized");

    R_TRUE
}

void shader_manager_class::shutdown()
{
    LOG_SHUTDOWN("Shutting down shader_manager_class");

    // Release the normal map shader object.
    if (normal_map_shader_)
    {
        normal_map_shader_->shutdown();
        delete normal_map_shader_;
        normal_map_shader_ = 0;
    }

    // Release the texture shader object.
    if (texture_shader_)
    {
        texture_shader_->shutdown();
        delete texture_shader_;
        texture_shader_ = 0;
    }

    // Release the multitexture shader object.
    if (multitexture_shader_)
    {
        multitexture_shader_->shutdown();
        delete multitexture_shader_;
        multitexture_shader_ = 0;
    }

    // Release the translate shader object.
    if (translate_shader_)
    {
        translate_shader_->shutdown();
        delete translate_shader_;
        translate_shader_ = 0;
    }

    // Release the alpha map shader object.
    if (alpha_map_shader_)
    {
        alpha_map_shader_->shutdown();
        delete alpha_map_shader_;
        alpha_map_shader_ = 0;
    }

    // Release the specular map shader object.
    if (spec_map_shader_)
    {
        spec_map_shader_->shutdown();
        delete spec_map_shader_;
        spec_map_shader_ = 0;
    }

    // Release the transparent shader object.
    if (transparent_shader_)
    {
        transparent_shader_->shutdown();
        delete transparent_shader_;
        transparent_shader_ = 0;
    }

    // Release the light shader object.
    if (light_shader_)
    {
        light_shader_->shutdown();
        delete light_shader_;
        light_shader_ = 0;
    }

    // Release the light map shader object.
    if (light_map_shader_)
    {
        light_map_shader_->shutdown();
        delete light_map_shader_;
        light_map_shader_ = 0;
    }

    // Release the refraction shader object.
    if (refraction_shader_)
    {
        refraction_shader_->shutdown();
        delete refraction_shader_;
        refraction_shader_ = 0;
    }

    // Release the water shader object.
    if (water_shader_)
    {
        water_shader_->shutdown();
        delete water_shader_;
        water_shader_ = 0;
    }

    // Release the cel shading shader object.
    if (cel_shading_shader_)
    {
        cel_shading_shader_->shutdown();
        delete cel_shading_shader_;
        cel_shading_shader_ = 0;
    }

	if (sunlight_shader_)
	{
		sunlight_shader_->shutdown();
		delete sunlight_shader_;
		sunlight_shader_ = 0;
	}

    if (skybox_shader_)
    {
        skybox_shader_->Shutdown();
        delete skybox_shader_;
        skybox_shader_ = 0;
    }

    if (depth_shader_)
    {
        depth_shader_->shutdown();
        delete depth_shader_;
        depth_shader_ = 0;
    }

    LOG_SHUTDOWN("shader_manager_class shut down");

    return;
}

bool shader_manager_class::render_texture_shader(ID3D11DeviceContext* deviceContext, int indexCount, XMMATRIX worldMatrix, XMMATRIX viewMatrix, XMMATRIX projectionMatrix,
    ID3D11ShaderResourceView* texture)
{
    bool result;

    result = texture_shader_->render(deviceContext, indexCount, worldMatrix, viewMatrix, projectionMatrix, texture);
    if (!result)
    {
        LOG_ERROR("Error rendering texture_shader_class");
        R_FALSE
    }

    R_TRUE
}

bool shader_manager_class::render_normal_map_shader(ID3D11DeviceContext* deviceContext, int indexCount, XMMATRIX worldMatrix, XMMATRIX viewMatrix, XMMATRIX projectionMatrix,
    ID3D11ShaderResourceView* colorTexture, ID3D11ShaderResourceView* normalTexture, XMFLOAT3 lightDirection, XMFLOAT4 diffuseColor)
{
    bool result;

    result = normal_map_shader_->render(deviceContext, indexCount, worldMatrix, viewMatrix, projectionMatrix, colorTexture, normalTexture, lightDirection, diffuseColor);
    if (!result)
    {
        LOG_ERROR("Error rendering normal_map_shader_class");
        R_FALSE
    }

    R_TRUE
}

bool shader_manager_class::render_multitexture_shader(ID3D11DeviceContext* deviceContext, int indexCount, XMMATRIX worldMatrix, XMMATRIX viewMatrix, XMMATRIX projectionMatrix,
    ID3D11ShaderResourceView* texture1, ID3D11ShaderResourceView* texture2)
{
    bool result;

    result = multitexture_shader_->render(deviceContext, indexCount, worldMatrix, viewMatrix, projectionMatrix, texture1, texture2);
    if (!result)
    {
        LOG_ERROR("Error rendering multi_texture_shader_class");
        R_FALSE
    }

    R_TRUE
}

bool shader_manager_class::render_translate_shader(ID3D11DeviceContext* deviceContext, int indexCount, XMMATRIX worldMatrix, XMMATRIX viewMatrix, XMMATRIX projectionMatrix,
    ID3D11ShaderResourceView* texture1, float valeur)
{
    bool result;

    result = translate_shader_->render(deviceContext, indexCount, worldMatrix, viewMatrix, projectionMatrix, texture1, valeur);
    if (!result)
    {
        LOG_ERROR("Error rendering translate_shader_class");
        R_FALSE
    }

    R_TRUE
}

bool shader_manager_class::render_alpha_map_shader(ID3D11DeviceContext* deviceContext, int indexCount, XMMATRIX worldMatrix, XMMATRIX viewMatrix, XMMATRIX projectionMatrix,
    ID3D11ShaderResourceView* texture1, ID3D11ShaderResourceView* texture2, ID3D11ShaderResourceView* texture3)
{
    bool result;

    result = alpha_map_shader_->render(deviceContext, indexCount, worldMatrix, viewMatrix, projectionMatrix, texture1, texture2, texture3);
    if (!result)
    {
        LOG_ERROR("Error rendering alpha_map_shader_class");
        R_FALSE
    }

    R_TRUE
}

bool shader_manager_class::render_spec_map_shader(ID3D11DeviceContext* deviceContext, int indexCount, XMMATRIX worldMatrix, XMMATRIX viewMatrix, XMMATRIX projectionMatrix,
    ID3D11ShaderResourceView* texture1, ID3D11ShaderResourceView* texture2, ID3D11ShaderResourceView* texture3,
    XMFLOAT3 lightDirection, XMFLOAT4 diffuseColor, XMFLOAT3 cameraPosition, XMFLOAT4 specularColor, float specularPower)
{
    bool result;

    result = spec_map_shader_->render(deviceContext, indexCount, worldMatrix, viewMatrix, projectionMatrix, texture1, texture2, texture3, lightDirection,
        diffuseColor, cameraPosition, specularColor, specularPower);
    if (!result)
    {
        LOG_ERROR("Error rendering spec_map_shader_class");
        R_FALSE
    }

    R_TRUE
}

bool shader_manager_class::render_transparent_shader(ID3D11DeviceContext* deviceContext, int indexCount, XMMATRIX worldMatrix, XMMATRIX viewMatrix, XMMATRIX projectionMatrix,
    ID3D11ShaderResourceView* texture1, float blendAmount)
{
    bool result;

    result = transparent_shader_->render(deviceContext, indexCount, worldMatrix, viewMatrix, projectionMatrix, texture1, blendAmount);
    if (!result)
    {
        LOG_ERROR("Error rendering transparent_shader_class");
        R_FALSE
    }

    R_TRUE
}

bool shader_manager_class::renderlight_shader(ID3D11DeviceContext* deviceContext, int indexCount, XMMATRIX worldMatrix, XMMATRIX viewMatrix, XMMATRIX projectionMatrix,
    ID3D11ShaderResourceView* texture, XMFLOAT4 diffuseColor[], XMFLOAT4 lightPosition[], XMFLOAT4 ambientColor[])
{
    bool result;

    result = light_shader_->render(deviceContext, indexCount, worldMatrix, viewMatrix, projectionMatrix, texture, diffuseColor, lightPosition, ambientColor);
    if (!result)
    {
        LOG_ERROR("Error rendering light_shader_class");
        R_FALSE
    }

    R_TRUE
}

bool shader_manager_class::renderlight_map_shader(ID3D11DeviceContext* deviceContext, int indexCount, XMMATRIX worldMatrix, XMMATRIX viewMatrix,
    XMMATRIX projectionMatrix, ID3D11ShaderResourceView* texture1, ID3D11ShaderResourceView* texture2)
{
    bool result;

    result = light_map_shader_->render(deviceContext, indexCount, worldMatrix, viewMatrix, projectionMatrix, texture1, texture2);
    if (!result)
    {
        LOG_ERROR("Error rendering light_map_shader_class");
        R_FALSE
    }

    R_TRUE
}

bool shader_manager_class::render_refraction_shader(ID3D11DeviceContext* deviceContext, int indexCount, XMMATRIX worldMatrix, XMMATRIX viewMatrix, XMMATRIX projectionMatrix,
    ID3D11ShaderResourceView* texture, XMFLOAT3 lightDirection, XMFLOAT4 ambientColor[], XMFLOAT4 diffuseColor[], XMFLOAT4 lightPosition[], XMFLOAT4 clipPlane)
{
    bool result;

    result = refraction_shader_->render(deviceContext, indexCount, worldMatrix, viewMatrix, projectionMatrix, texture, lightDirection, ambientColor, diffuseColor, lightPosition, clipPlane);
    if (!result)
    {
        LOG_ERROR("Error rendering refraction_shader_class");
        R_FALSE
    }

    R_TRUE
}

bool shader_manager_class::render_water_shader(ID3D11DeviceContext* deviceContext, int indexCount, XMMATRIX worldMatrix, XMMATRIX viewMatrix, XMMATRIX projectionMatrix,
    XMMATRIX reflectionMatrix, ID3D11ShaderResourceView* reflectionTexture, ID3D11ShaderResourceView* refractionTexture,
    ID3D11ShaderResourceView* normalTexture, float waterTranslation, float reflectRefractScale)
{
    bool result;

    result = water_shader_->render(deviceContext, indexCount, worldMatrix, viewMatrix, projectionMatrix, reflectionMatrix, reflectionTexture,
        refractionTexture, normalTexture, waterTranslation, reflectRefractScale);
    if (!result)
    {
        LOG_ERROR("Error rendering water_shader_class");
        R_FALSE
    }

    R_TRUE
}

bool shader_manager_class::render_cel_shading_shader(ID3D11DeviceContext* deviceContext, int indexCount, XMMATRIX worldMatrix, XMMATRIX viewMatrix, XMMATRIX projectionMatrix,
    ID3D11ShaderResourceView* texture, XMFLOAT4 diffuseColor, XMFLOAT4 ambientColor, XMFLOAT3 sunDirection, float sunIntensity)
{
    bool result;

    result = cel_shading_shader_->render(deviceContext, indexCount, worldMatrix, viewMatrix, projectionMatrix, texture, diffuseColor, ambientColor, sunDirection, sunIntensity);
    if (!result)
    {
        LOG_ERROR("Error rendering celshade_class");
        R_FALSE
    }

    R_TRUE
}

bool shader_manager_class::render_sunlight_shader(ID3D11DeviceContext* deviceContext, int indexCount, XMMATRIX worldMatrix, XMMATRIX viewMatrix, XMMATRIX projectionMatrix,
	ID3D11ShaderResourceView* texture, XMFLOAT4 diffuseColor, XMFLOAT4 ambientColor, XMFLOAT3 sunDirection, float sunIntensity)
{
	bool result;

	result = sunlight_shader_->render(deviceContext, indexCount, worldMatrix, viewMatrix, projectionMatrix, texture, diffuseColor, ambientColor, sunDirection, sunIntensity);
	if (!result)
	{
	    LOG_ERROR("Error rendering sunlight_shader_class");
		R_FALSE
	}

	R_TRUE
}

bool shader_manager_class::render_skybox_shader(ID3D11DeviceContext* deviceContext, int indexCount, XMMATRIX worldMatrix, XMMATRIX viewMatrix, XMMATRIX projectionMatrix,
    ID3D11ShaderResourceView* texture, XMFLOAT4 diffuseColor, XMFLOAT4 ambientColor, XMFLOAT3 sunDirection, float sunIntensity)
{
    bool result;

    result = skybox_shader_->Render(deviceContext, indexCount, worldMatrix, viewMatrix, projectionMatrix, texture, diffuseColor, ambientColor, sunDirection, sunIntensity);
    if (!result)
    {
        LOG_ERROR("Error rendering skybox_shader_class");
        R_FALSE
    }

    R_TRUE
}

bool shader_manager_class::render_depth_shader(
    ID3D11DeviceContext* context,
    int indexCount,
    XMMATRIX worldMatrix,
    XMMATRIX viewMatrix,
    XMMATRIX projectionMatrix
)
{
    bool result;

    result = depth_shader_->render(context, indexCount, worldMatrix, viewMatrix, projectionMatrix);
    if (!result)
    {
        LOG_ERROR("Error rendering depth_shader_class");
        R_FALSE
    }

    R_TRUE
}