#include <pch.hpp>

#include "logging.hpp"
#include <fastgltf.hpp>
#include "ref_scope.hpp"

#include <cstddef>
#include <cstdint>
#include <glm/fwd.hpp>
#include <fastgltf/core.hpp>
#include <fastgltf/types.hpp>
#include <fastgltf/tools.hpp>
#include <fastgltf/glm_element_traits.hpp>

#include <vector>

namespace OpenEngine {

    void loadPrimitive(fastgltf::Asset& asset,
            fastgltf::Primitive& primitive,
            Mesh& out)
    {
        if (primitive.indicesAccessor.has_value()) {
            auto& accessor = asset.accessors[primitive.indicesAccessor.value()];
            out.indices.resize(accessor.count);

            fastgltf::iterateAccessorWithIndex<uint32_t>(asset, accessor,
                    [&](uint32_t index, size_t i) {
                        out.indices[i] = index;
                    });
        }

        {
            auto* position_iterator = primitive.findAttribute("POSITION");
            auto& accessor = asset.accessors[position_iterator->accessorIndex];
            out.vertices.resize(accessor.count);
            
            fastgltf::iterateAccessorWithIndex<glm::vec3>(asset, accessor,
                    [&](glm::vec3 pos, size_t i) {
                        out.vertices[i].position = pos;
                    });
        }

        if (auto* normal_iterator = primitive.findAttribute("NORMAL");
                normal_iterator != primitive.attributes.end()) {
            auto& accessor = asset.accessors[normal_iterator->accessorIndex];

            fastgltf::iterateAccessorWithIndex<glm::vec3>(asset, accessor,
                    [&](glm::vec3 norm, size_t i) {
                        out.vertices[i].normal = norm;
                    });
        }

        {
            if (primitive.materialIndex.has_value()) {
                auto& material = asset.materials[primitive.materialIndex.value()];
                auto& pbr = material.pbrData;

                auto& c = pbr.baseColorFactor;
            }
        }
    }

    Ref<Mesh> TestGLTF()
    {
        fastgltf::Parser parser;
        Ref<Mesh> new_mesh = CreateRef<Mesh>();

        auto data = fastgltf::GltfDataBuffer::FromPath("assets/models/cube.glb");
        if (data.error() != fastgltf::Error::None)
            OE_CORE_ERROR("Could not parse model");

        auto asset = parser.loadGltfBinary(data.get(), ".",
                fastgltf::Options::LoadExternalBuffers
                );
        if (asset.error() != fastgltf::Error::None)
            OE_CORE_ERROR("Could not optain asset");

        for (auto& mesh : asset->meshes)
            for (auto& primitive : mesh.primitives)
                loadPrimitive(asset.get(), primitive, *new_mesh);

        return new_mesh;
    }

}
