#include <PipelineStage/DrawStage/ModelStage/ModelStage.hpp>
#include <FrameDrawer/FrameDrawer.hpp>
#include <Display/WidgetDisplay/WorldDisplay/WorldDisplay.hpp>
#include <IndexedUnitCube/IndexedUnitCube.hpp>
#include <Vk/ShaderConst.hpp>

ModelStage::ModelStage(
    FrameDrawer &frameDrawer,
    std::shared_ptr<Vk::DescriptorSet> dataDescSet
) :
    DrawStage(
        "Models",
        frameDrawer,
        *frameDrawer.worldDisplay.modelRenderPass,
        *frameDrawer.worldDisplay.modelFramebuffer,
        *frameDrawer.worldDisplay.modelPipeline,
        {}
    ),
    dataDescSet(dataDescSet)
{}

void ModelStage::setModelMatrix(const glm::mat4 &modelMatrix)
{
    ModelData data;
    data.modelMatrix = modelMatrix;
    data.antiMVP = glm::inverse(frameDrawer.projMatrix * frameDrawer.viewMatrix * modelMatrix);

    cmdbuf->pushConstants(
        pipeline,
        VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT,
        0,
        sizeof(ModelData),
        &data
    );
}

void ModelStage::drawModel(Vk::DescriptorSet &descSet)
{
    cmdbuf->bindDescriptorSet(
        VK_PIPELINE_BIND_POINT_GRAPHICS,
        pipeline,
        GLSL_MODEL_DESCRIPTOR_SET,
        descSet
    );

    cmdbuf->draw(36, 1, 0, 0);
}

void ModelStage::onFrameBegins()
{
    cmdbuf->bindDescriptorSet(
        VK_PIPELINE_BIND_POINT_GRAPHICS,
        pipeline,
        GLSL_MODEL_FRAME_DESCRIPTOR_SET,
        *dataDescSet
    );
}