#pragma once

#include <vulkan/vulkan.h>
#include "SceneObject.h"


/**
 * Represents a house object within a Vulkan-rendered scene.
 * Inherits from SceneObject to leverage common object properties and functionalities.
 */
class CrossObject : public SceneObject{
    public:
    
     /**
     * Constructor for the HouseObject.
     * Initializes the house geometry and invokes the base SceneObject constructor.
     * Scalability
     * 
     * @param dev The Vulkan device.
     * @param phyDev The physical Vulkan device.
     * @param descPool The descriptor pool for allocating descriptor sets.
     * @param descSetLayout The layout of the descriptor set.
     * @param queue The Vulkan queue to which rendering commands will be submitted.
     */
        CrossObject(VkDevice dev, VkPhysicalDevice phyDev, VkDescriptorPool descPool, VkDescriptorSetLayout descSetLayout, VkQueue queue, ShadowMap& shadowMap)
        : SceneObject(dev, phyDev, descPool, descSetLayout, queue,  { {{-0.2f,  0.2f, 0.0f}}, {{-0.2f, -0.2f, 0.0f}}, {{ 0.2f,  0.2f, 0.0f}}, {{ 0.2f, -0.2f, 0.0f}} }, {0, 1, 2, 1, 3, 2}, 
            sampler, cmdPool, sync, pfn, shadowMap)
        {
            GeometryData data;
            data.positions = {{-0.2f,  0.2f, 0.0f}, {-0.2f, -0.2f, 0.0f}, { 0.2f,  0.2f, 0.0f}, {0.2f, -0.2f, 0.0f}};
            data.textureCoordinates = { {0,1}, {0,0}, {1,1}, {1,0} };
            data.indices = {0, 1, 2, 1, 3, 2};
            data.normals = {
                {0.0f, 0.0f, 1.0f}, // Normal for all vertices (facing forward)
                {0.0f, 0.0f, 1.0f},
                {0.0f, 0.0f, 1.0f},
                {0.0f, 0.0f, 1.0f}
            };
            data.tangents = {
                {0.0f, 0.0f, 0.0f}, // Red for top-left corner
                {0.0f, 0.0f, 0.0f}, // Green for bottom-left corner
                {0.0f, 0.0f, 1.0f}, // Blue for top-right corner
                {0.0f, 0.0f, 0.0f}  // Yellow for bottom-right corner
            };
            sceneObjectGeometry = createAndUploadIntoGpuMemory(data);
            uniformBuffer = vklCreateHostCoherentBufferWithBackingMemory(
                sizeof(UniformBuffer), VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT
            );
            descriptorSet = allocDescriptorSet(dev, descPool, descSetLayout);
            writeDescriptorSet(dev, descriptorSet, uniformBuffer);
            worldTransform = glm::mat4(1.0f); // identity
            localTransform = glm::mat4(1.0f);

            writeDescriptorSet(dev, descriptorSet, shadowMap.m_image_view, shadowMap.m_image_sampler, 1);
        
        }

    /**
     * Updates the uniform buffer with transformation matrices and other data.
     * This function should be called every frame to update shader data based on transformations.
     */
    virtual void updateUniformBuffer(Student::CameraForGLFW& camera, const glm::vec4& windowSize, const FrameTimer& frameTimer) 
    {
        ubo.modelMatrix = glm::mat4(1.0f);  // This trafo controls how big the trnasparent quad is. it should be small .
        ubo.modelViewProjMatrix = glm::mat4(1.0f);  // Combine with the camera matrix
        ubo.userInput = glm::ivec4(0, windowSize.x, windowSize.y, 1 ); // last index tells that this renders cross
        vklCopyDataIntoHostCoherentBuffer(this->uniformBuffer, &ubo, sizeof(ubo));
    }

    virtual void updateUniformBufferForShadow(ShadowMap shadowMap, Spotlight spotlight)
    {
        // THis object does not have a shadow
    }

    /**
     * Records the Vulkan rendering commands for the house object.
     * Binds the necessary Vulkan resources and issues the draw call.
     * 
     * @param commandBuffer The command buffer to record the rendering commands.
     * @param pipeline_layout The pipeline layout used for descriptor binding.
     * @param pipeline The graphics pipeline to use for rendering the house.
     */
    void recordRenderingCommands(VkCommandBuffer commandBuffer, VkPipeline hudPipeline, VkPipeline specularPipeline, VkPipeline normalPipeline, VkPipeline normalheightPipeline, const FrameTimer& frameTimer){
    
        drawGeometryWithMaterial(hudPipeline, this->sceneObjectGeometry, descriptorSet);
    }

    virtual void recordRenderingCommandsForShadowMap(ShadowMap& shadowMap, const Spotlight& spotlight)
    {
        // The screen quad is meant to render the aiming cross and does not throw a shadow iteself
    }


};

