#include "FactoryCraftModel.h"

#include <Shader.h>

#include "CustomDX11API.h"
#include "Globals.h"
#include "World.h"

FactoryCraftModel::FactoryCraftModel()
    : Model3D()
{
    vertexLightBuffer = 0;
    lightBuffer = 0;
    vertexLightBufferCount = 0;
    visible = 1;
    destroyedState = 0;
    breakTextur
        = uiFactory.initParam.bildschirm->zGraphicsApi()->createOrGetTexture(
            "blocks.ltdb/crack.png", 0);
    effectAlpha = 0;
    memset(averageLight, 0, 8);
    *(int*)averageLight = 0xFFFFFF00;
    fallbackVertexLightBuffer = uiFactory.initParam.bildschirm->zGraphicsApi()
                                    ->createStructuredBuffer(16);
    fallbackVertexLightBuffer->setData(averageLight);
}

FactoryCraftModel::~FactoryCraftModel()
{
    breakTextur->release();
    if (vertexLightBuffer) vertexLightBuffer->release();
    fallbackVertexLightBuffer->release();
    delete[] lightBuffer;
}

struct TexturEffect
{
    bool enabled;
    float percentage;
};

void FactoryCraftModel::beforeRender(Framework::GraphicsApi* api,
    Framework::Shader* zVertexShader,
    Framework::Shader* zPixelShader)
{
    if (!World::INSTANCE) return;
    CustomDX11API* cApi = dynamic_cast<CustomDX11API*>(api);
    if (cApi)
    {
        char buffer[8];
        *(int*)buffer
            = vertexLightBufferCount == 0 ? 1 : vertexLightBufferCount;
        *(float*)(buffer + 4) = World::INSTANCE->getDayLightFactor();
        zVertexShader->fillConstBuffer(
            buffer, cApi->getVertexShaderLightBufferIndex(), 8);
        if (vertexLightBuffer)
        {
            vertexLightBuffer->copyToGPU();
            cApi->setVertexLightBuffer(vertexLightBuffer);
        }
        else
        {
            fallbackVertexLightBuffer->copyToGPU(8);
            cApi->setVertexLightBuffer(fallbackVertexLightBuffer);
        }
        if (destroyedState > 0 && effectAlpha)
        {
            TexturEffect e = {1, 1.f + destroyedState};
            zPixelShader->fillConstBuffer((char*)&e, 3, sizeof(TexturEffect));
        }
    }
}

void FactoryCraftModel::afterRender(Framework::GraphicsApi* api,
    Framework::Shader* zVertexShader,
    Framework::Shader* zPixelShader)
{
    if (!World::INSTANCE) return;
    CustomDX11API* cApi = dynamic_cast<CustomDX11API*>(api);
    if (cApi)
    {
        char buffer[8];
        *(int*)buffer = 0;
        *(float*)(buffer + 4) = World::INSTANCE->getDayLightFactor();
        zVertexShader->fillConstBuffer(
            buffer, cApi->getVertexShaderLightBufferIndex(), 8);
    }
}

void FactoryCraftModel::setVertexLightBuffer(__int64* data, int vertexCount)
{
    if (!vertexLightBuffer)
    {
        vertexLightBuffer = uiFactory.initParam.bildschirm->zGraphicsApi()
                                ->createStructuredBuffer(16);
    }
    if (lightBuffer)
    {
        delete[] lightBuffer;
    }
    lightBuffer = data;
    vertexLightBufferCount = vertexCount;
    vertexLightBuffer->setData(data);
    vertexLightBuffer->setLength(vertexCount * 8);
    vertexLightBuffer->setChanged();
}

__int64* FactoryCraftModel::zLightBuffer()
{
    return lightBuffer;
}

void FactoryCraftModel::copyLightToGPU()
{
    vertexLightBuffer->setChanged();
}

void FactoryCraftModel::setVisible(bool visible)
{
    this->visible = visible;
}

void FactoryCraftModel::setDestroyedState(float percentage)
{
    destroyedState = percentage;
}

void FactoryCraftModel::setUseEffectAlpha(bool useAlpha)
{
    effectAlpha = useAlpha;
}

bool FactoryCraftModel::needRenderPolygon(int index)
{
    return visible;
}

Texture* FactoryCraftModel::zEffectTexture()
{
    return destroyedState > 0 ? breakTextur : 0;
}

float FactoryCraftModel::getEffectPercentage()
{
    return destroyedState;
}

void FactoryCraftModel::setAverageLight(unsigned char light[3])
{
    *(averageLight + 5) = light[2];
    *(averageLight + 6) = light[1];
    *(averageLight + 7) = light[0];
    fallbackVertexLightBuffer->setChanged();
}
