// gpu_device.hpp - Wrapper de SDL_GPUDevice
// © 2025 Orni Attack
//
// Ownership del SDL_GPUDevice y del claim del window. Backend preferido:
// Vulkan (Linux, Windows) y Metal (macOS). Sin DirectX.
//
// Uso:
//   GpuDevice device;
//   if (!device.init(window)) return -1;       // claim del window
//   ... renderer setup ...
//   device.destroy();                          // unclaim + destroy device

#pragma once

#include <SDL3/SDL.h>
#include <SDL3/SDL_gpu.h>

#include <string>

namespace Rendering::GPU {

class GpuDevice {
    public:
        GpuDevice() = default;
        ~GpuDevice();

        // No copia / move (RAII propietario del device).
        GpuDevice(const GpuDevice&) = delete;
        auto operator=(const GpuDevice&) -> GpuDevice& = delete;
        GpuDevice(GpuDevice&&) = delete;
        auto operator=(GpuDevice&&) -> GpuDevice& = delete;

        // Crea el device y claim el window. Devuelve false si no hay backend
        // soportado o si el driver no permite el claim.
        [[nodiscard]] auto init(SDL_Window* window) -> bool;
        void destroy();

        // Carga un shader SPIR-V desde build/shaders/{name}.spv. Devuelve un
        // SDL_GPUShader* del que ahora es responsable el caller (libera con
        // SDL_ReleaseGPUShader). Retorna nullptr si falla.
        //
        // num_uniform_buffers: nº de uniform buffers que usa el shader (slot 0..N-1).
        // num_samplers: nº de samplers (combined image+sampler) usados por el shader.
        [[nodiscard]] auto loadShader(const std::string& spv_filename,
                                      SDL_GPUShaderStage stage,
                                      uint32_t num_uniform_buffers,
                                      uint32_t num_samplers = 0) const -> SDL_GPUShader*;

        [[nodiscard]] auto get() const -> SDL_GPUDevice* { return device_; }
        [[nodiscard]] auto window() const -> SDL_Window* { return window_; }
        [[nodiscard]] auto swapchainFormat() const -> SDL_GPUTextureFormat { return swapchain_format_; }

    private:
        SDL_GPUDevice* device_{nullptr};
        SDL_Window* window_{nullptr};
        SDL_GPUTextureFormat swapchain_format_{SDL_GPU_TEXTUREFORMAT_INVALID};
};

}  // namespace Rendering::GPU
