#pragma once

#include "shader.h"
#include "util.h"

#include <functional>

namespace pp::panopainter {

struct LegacyStrokePadUniforms {
    glm::vec4 color {};
    bool uses_destination_feedback = false;
};

struct LegacyStrokeDilateUniforms {
    glm::mat4 mvp { 1.0f };
};

struct LegacyStrokeEdgeShaderExecution {
    std::function<void(kShader)> use_shader;
    std::function<void(kShaderUniform, int)> set_int;
    std::function<void(kShaderUniform, const glm::vec4&)> set_vec4;
    std::function<void(kShaderUniform, const glm::mat4&)> set_mat4;
};

[[nodiscard]] inline LegacyStrokeEdgeShaderExecution legacy_shader_manager_stroke_edge_execution() noexcept
{
    return {
        .use_shader = [](kShader shader) { ShaderManager::use(shader); },
        .set_int = [](kShaderUniform uniform, int value) { ShaderManager::u_int(uniform, value); },
        .set_vec4 = [](kShaderUniform uniform, const glm::vec4& value) { ShaderManager::u_vec4(uniform, value); },
        .set_mat4 = [](kShaderUniform uniform, const glm::mat4& value) { ShaderManager::u_mat4(uniform, value); },
    };
}

inline void setup_legacy_stroke_pad_shader(
    const LegacyStrokePadUniforms& uniforms,
    const LegacyStrokeEdgeShaderExecution& execution) noexcept
{
    execution.use_shader(kShader::StrokePad);
    execution.set_vec4(kShaderUniform::Col, uniforms.color);
    if (uniforms.uses_destination_feedback) {
        execution.set_int(kShaderUniform::TexBG, 1);
    }
}

inline void setup_legacy_stroke_pad_shader(const LegacyStrokePadUniforms& uniforms)
{
    setup_legacy_stroke_pad_shader(uniforms, legacy_shader_manager_stroke_edge_execution());
}

inline void setup_legacy_stroke_dilate_shader(
    const LegacyStrokeDilateUniforms& uniforms,
    const LegacyStrokeEdgeShaderExecution& execution) noexcept
{
    execution.use_shader(kShader::StrokeDilate);
    execution.set_mat4(kShaderUniform::MVP, uniforms.mvp);
    execution.set_int(kShaderUniform::TexBG, 0);
}

inline void setup_legacy_stroke_dilate_shader(const LegacyStrokeDilateUniforms& uniforms)
{
    setup_legacy_stroke_dilate_shader(uniforms, legacy_shader_manager_stroke_edge_execution());
}

} // namespace pp::panopainter
