#ifndef VULKAN_DESCRIPTOR_SET_HPP_
#define VULKAN_DESCRIPTOR_SET_HPP_

#include <Utilities/Extern.hpp>
#include <Vk/Device/Device.hpp>
#include <Vk/DescriptorPool/DescriptorPool.hpp>
#include <Vk/DescriptorSetLayout/DescriptorSetLayout.hpp>
#include <Vk/ImageView/ImageView.hpp>
#include <Vk/Sampler/Sampler.hpp>
#include <Vk/Buffer/Buffer.hpp>

namespace Vk
{
    /**
     * @brief Represents a Vulkan descriptor set.
     */
    class DescriptorSet
    {
    private:
        std::shared_ptr<Vk::Device> m_device;
        std::shared_ptr<Vk::DescriptorPool> m_pool;
        VkDescriptorSet m_descriptorSet;
    
    public:
        /**
         * @brief Construct a new descriptor set.
         * 
         * @param device The device.
         * @param pool The pool from which to allocate.
         * @param layout The descriptor set layout.
         */
        DescriptorSet(
            std::shared_ptr<Vk::Device> device,
            std::shared_ptr<Vk::DescriptorPool> pool,
            std::shared_ptr<Vk::DescriptorSetLayout> layout
        );
        DescriptorSet(const DescriptorSet &) = delete;

        ~DescriptorSet();

        /**
         * @brief Return the wrapped descriptor set.
         */
        VkDescriptorSet inner();

        /**
         * @brief Set the specified descriptor index to a combined image sampler.
         */
        void setImageSampler(int index, Vk::ImageView& imageView, Vk::Sampler& sampler);

        /**
         * @brief Set the specified descriptor index to a uniform buffer.
         */
        void setUniformBuffer(int index, Vk::Buffer &buffer, size_t offset, size_t size);

        /**
         * @brief Set the specified descriptor index to a storage buffer.
         */
        void setStorageBuffer(int index, Vk::Buffer &buffer, size_t offset, size_t size);

        /**
         * @brief Set the specified descriptor index to a storage image.
         */
        void setStorageImage(int index, Vk::ImageView& imageView);
    };
}

#endif