#pragma once

#include <SDL3/SDL.h>

#include <filesystem>
#include <memory>
#include <string>

namespace Rendering {

    struct ShaderMetadata {
        std::string name;
        std::string author;
        std::string iChannel0{"none"};
        std::string iChannel1{"none"};
        std::string iChannel2{"none"};
        std::string iChannel3{"none"};
    };

    struct ShaderUniforms {
        float iTime{0.0f};
        float iResolutionX{0.0f};
        float iResolutionY{0.0f};
    };

    struct ShaderProgramSpec {
        std::filesystem::path folder;
        std::string base_name;
        ShaderMetadata metadata;
    };

    class IShaderBackend {
       public:
        IShaderBackend() = default;
        virtual ~IShaderBackend() = default;

        IShaderBackend(const IShaderBackend&) = delete;
        IShaderBackend(IShaderBackend&&) = delete;
        auto operator=(const IShaderBackend&) -> IShaderBackend& = delete;
        auto operator=(IShaderBackend&&) -> IShaderBackend& = delete;

        virtual auto init(SDL_Window* window) -> bool = 0;
        virtual auto loadShader(const ShaderProgramSpec& spec) -> bool = 0;
        virtual void render(const ShaderUniforms& uniforms) = 0;
        virtual void setVSync(bool vsync) = 0;
        virtual void cleanup() = 0;
        [[nodiscard]] virtual auto driverName() const -> std::string = 0;
    };

    [[nodiscard]] auto makeOpenGLBackend() -> std::unique_ptr<IShaderBackend>;
    [[nodiscard]] auto makeSdl3GpuBackend() -> std::unique_ptr<IShaderBackend>;

    [[nodiscard]] auto extractShaderMetadata(const std::string& source) -> ShaderMetadata;
    [[nodiscard]] auto loadFileToString(const std::filesystem::path& path, std::string& out) -> bool;
    [[nodiscard]] auto parseMetaFile(const std::filesystem::path& meta_path) -> ShaderMetadata;

}  // namespace Rendering
