/**
 *
 * @file src/render/vulkan/Vulkan_window_renderer.hpp
 *
 * @copyright 2008-2024 Bordeaux INP, CNRS (LaBRI UMR 5800), Inria,
 *                      Univ. Bordeaux. All rights reserved.
 *
 * @author Camille Ordronneau
 * @author Johnny Jazeix
 * @author Nolan Bredel
 * @author Lucas Guedon
 * @author Augustin Gauchet
 *
 * @date 2024-07-17
 */

#ifndef VULKAN_WINDOW_RENDERER_HPP
#define VULKAN_WINDOW_RENDERER_HPP

#include <QVulkanWindow>
#include "common/common.hpp"
#include "core/Core.hpp"
#include "interface/Interface_graphic.hpp"
#include "render/vulkan/Vk_vertex_buffer.hpp"
#include "render/vulkan/Vk_uniform_buffer.hpp"
#include "render/vulkan/Vk_pipeline.hpp"

/*!
 * \brief The internal representation of a vertex
 */
struct Vertex
{
public:
    Element_pos x, y;
    Element_col r, g, b;

    Vertex(Element_pos x, Element_pos y, Element_col r, Element_col g, Element_col b) :
        x(x), y(y), r(r), g(g), b(b) { }
};

class Vulkan_window_renderer : public QVulkanWindowRenderer
{
public:
    Vulkan_window_renderer(Interface_graphic *interface_graphic, QVulkanWindow *w);
    void initResources() override;
    void initSwapChainResources() override;
    void releaseSwapChainResources() override;
    void releaseResources() override;
    void startNextFrame() override;

protected:
    /*!
     * \brief Loads a compiled shader from the file with the given name
     */
    VkShaderModule create_shader(const QString &shader_name);
    /*!
     * \brief Creates the descriptor pool required for the rendering
     */
    void create_descriptor_pool();
    /*!
     * \brief Creates the pipeline required for the rendering
     */
    void create_pipeline();
    void draw_vertices(Vk_uniform_buffer *uniform_buf, Vk_vertex_buffer *vertex_buf);

    Interface_graphic *_interface_graphic;
    QVulkanWindow *_window;
    QVulkanDeviceFunctions *_dev_funcs;

    Vk_uniform_buffer _buf_container_uniform;
    Vk_uniform_buffer _buf_state_uniform;
    Vk_uniform_buffer _buf_static_uniform;

    VkDescriptorPool _desc_pool = VK_NULL_HANDLE;
    VkDescriptorSetLayout _desc_set_layout = VK_NULL_HANDLE;
    VkPipelineCache _pipeline_cache = VK_NULL_HANDLE;
    VkPipelineLayout _pipeline_layout = VK_NULL_HANDLE;
    Vk_pipeline _triangle_pipeline;
    Vk_pipeline _line_pipeline;

    /*!
     * \brief The current projection matrix, to addapt the view to the size of the window
     */
    QMatrix4x4 _proj;

public:
    /*!
     * \brief The current model matrix for rendering states, representing the translation and scale applied to the view
     */
    QMatrix4x4 state_model_view;
    /*!
     * \brief The current model matrix for rendering containers, representing the translation and scale applied to the view
     */
    QMatrix4x4 container_model_view;
    Vk_vertex_buffer buf_container_vertex;
    Vk_vertex_buffer buf_state_vertex;
    Vk_vertex_buffer buf_ruler;
    Vk_vertex_buffer buf_counter;
};

#endif
