#pragma once

/*
	GameEngine and Editor
	by John Ryland
	Copyright (c) 2023
*/

////////////////////////////////////////////////////////////////////////////////////
//	Model

#include <vector>
#include "VulkanAttributeBinding.h"

namespace Render {

enum class VertexInputRate : uint32_t
{
    VERTEX = 0,
    INSTANCE = 1
};

struct VertexBindingDescription
{
    uint32_t         binding;
    uint32_t         stride;
    VertexInputRate  inputRate;
};

enum class Format : uint32_t
{
    UNDEFINED = 0,
    R8G8_UINT = 20,
    R8G8_SINT = 21,
    R8G8B8_UNORM = 23,
    R8G8B8_SNORM = 24,
    R8G8B8_USCALED = 25,
    R8G8B8_SSCALED = 26,
    R8G8B8_UINT = 27,
    R8G8B8_SINT = 28,
    R8G8B8_SRGB = 29,
    A8B8G8R8_UNORM_PACK32 = 51,
    A8B8G8R8_SNORM_PACK32 = 52,
    A8B8G8R8_USCALED_PACK32 = 53,
    A8B8G8R8_SSCALED_PACK32 = 54,
    A8B8G8R8_UINT_PACK32 = 55,
    A8B8G8R8_SINT_PACK32 = 56,
    A8B8G8R8_SRGB_PACK32 = 57,
    R32_UINT = 98,
    R32G32_UINT = 101,
    R32_SINT = 99,
    R32G32_SINT = 102,
    R32_SFLOAT = 100,
    R32G32_SFLOAT = 103,
    R32G32B32_SFLOAT = 106,
    R64_SINT = 111,
    R64_SFLOAT = 112,
    R64G64B64_UINT = 116,
    R64G64B64_SINT = 117,
    R64G64B64_SFLOAT = 118,
    ASTC_4x4_SRGB_BLOCK = 158,
    ASTC_8x8_SRGB_BLOCK = 172,
    ASTC_12x12_SRGB_BLOCK = 184,
    G8_B8_R8_3PLANE_420_UNORM = 1000156002,
    G8_B8_R8_3PLANE_422_UNORM = 1000156004,
    G8_B8_R8_3PLANE_444_UNORM = 1000156006,
};

struct VertexAttributeDescription
{
    uint32_t    location;
    uint32_t    binding;
    Format      format;
    uint32_t    offset;
};

class Model
{
public:
    Model();
    ~Model();

    void Load(const char* fileName);

    // TODO: Need some kind of render backend neutral interface inbetween here and vulkan to adapt the binding/attribute descriptions
    std::vector<VkVertexInputBindingDescription>    GetVertexBindingDescriptions();
    std::vector<VkVertexInputAttributeDescription>  GetVertexAttributeDescriptions();

    void GetVertexData(const uint8_t* &data, uint64_t& size);
    void GetIndexData(const uint8_t* &data, uint64_t& size);
    uint32_t GetIndexCount();

private:
    struct ModelData;
    ModelData*          m_model;
};

} // Render namespace
