#pragma once

#include <SDL3/SDL.h>

#include <string>
#include <utility>

namespace Rendering {

    /** @brief Identificador del shader de post-procesado activo */
    enum class ShaderType { POSTFX,
        CRTPI };

    /**
     * @brief Parámetros de intensidad de los efectos PostFX
     */
    struct PostFXParams {
        float vignette = 0.0F;
        float scanlines = 0.0F;
        float chroma = 0.0F;
        float mask = 0.0F;
        float gamma = 0.0F;
        float curvature = 0.0F;
        float bleeding = 0.0F;
        float flicker = 0.0F;
    };

    /**
     * @brief Parámetros del shader CRT-Pi (algoritmo de scanlines continuas)
     */
    struct CrtPiParams {
        float scanline_weight{6.0F};
        float scanline_gap_brightness{0.12F};
        float bloom_factor{3.5F};
        float input_gamma{2.4F};
        float output_gamma{2.2F};
        float mask_brightness{0.80F};
        float curvature_x{0.05F};
        float curvature_y{0.10F};
        int mask_type{2};
        bool enable_scanlines{true};
        bool enable_multisample{true};
        bool enable_gamma{true};
        bool enable_curvature{false};
        bool enable_sharper{false};
    };

    /**
     * @brief Interfaz abstracta para backends de renderizado con shaders
     */
    class ShaderBackend {
       public:
        virtual ~ShaderBackend() = default;

        virtual auto init(SDL_Window* window,
            SDL_Texture* texture,
            const std::string& vertex_source,
            const std::string& fragment_source) -> bool = 0;

        virtual void render() = 0;
        virtual void setTextureSize(float width, float height) = 0;
        virtual void cleanup() = 0;

        virtual void uploadPixels(const Uint32* /*pixels*/, int /*width*/, int /*height*/) {}
        virtual void setPostFXParams(const PostFXParams& /*p*/) {}
        virtual void setVSync(bool /*vsync*/) {}
        virtual void setScaleMode(bool /*integer_scale*/) {}
        virtual void setOversample(int /*factor*/) {}

        virtual void setLinearUpscale(bool /*linear*/) {}
        [[nodiscard]] virtual auto isLinearUpscale() const -> bool { return false; }

        virtual void setDownscaleAlgo(int /*algo*/) {}
        [[nodiscard]] virtual auto getDownscaleAlgo() const -> int { return 0; }

        [[nodiscard]] virtual auto getSsTextureSize() const -> std::pair<int, int> { return {0, 0}; }

        [[nodiscard]] virtual auto isHardwareAccelerated() const -> bool = 0;

        [[nodiscard]] virtual auto getDriverName() const -> std::string { return {}; }
        virtual void setPreferredDriver(const std::string& /*driver*/) {}

        virtual void setActiveShader(ShaderType /*type*/) {}
        virtual void setCrtPiParams(const CrtPiParams& /*p*/) {}
        [[nodiscard]] virtual auto getActiveShader() const -> ShaderType { return ShaderType::POSTFX; }
    };

}  // namespace Rendering
