#pragma once

#include "Kit/EngineManager.h"
#include <tl/vector.h>

#include <filament/IndexBuffer.h>
#include <filament/Material.h>
#include <filament/MaterialInstance.h>
#include <filament/Texture.h>
#include <filament/VertexBuffer.h>
#include <utils/Entity.h>

#include "IUI/ImGui/imgui.h"

struct ImDrawData;
struct ImGuiIO;
struct ImGuiContext;

namespace kit
{

// Translates ImGui's draw commands into Filament primitives, textures, vertex buffers, etc.
// Creates a UI-specific Scene object and populates it with a Renderable. Does not handle
// event processing; clients can simply call ImGui::GetIO() directly and set the mouse state.
class ImGuiFilamentBridge
{
public:
	// The constructor creates its own Scene and places it in the given View.
	ImGuiFilamentBridge(tl::lent_ref<EngineManager> engineManager, tl::lent_ref<filament::Scene> flmScene);
	~ImGuiFilamentBridge();

	// Low-level alternative to render() that consumes an ImGui command list and translates it into
	// various Filament calls. This includes updating the vertex buffer, setting up material
	// instances, and rebuilding the Renderable component that encompasses the entire UI. Since this
	// makes Filament calls, it must be called from the main thread.
	void processImGuiCommands(ImDrawData& commands, const ImGuiIO& io);

	// Helper method called after resolving fontPath; public so fonts can be added by caller.
	ImTextureID createAtlasTexture();

private:
	void createBuffers(int numRequiredBuffers);
	void populateVertexData(size_t bufferIndex,
	                        size_t vbSizeInBytes,
	                        void* vbData,
	                        size_t ibSizeInBytes,
	                        void* ibData);
	tl::unique_ref<filament::VertexBuffer> createVertexBuffer(size_t capacity) const;
	tl::unique_ref<filament::IndexBuffer> createIndexBuffer(size_t capacity) const;
	tl::lent_ref<EngineManager> m_engineManager;
	tl::lent_ref<filament::Scene> m_scene;
	tl::unique_ptr<filament::Material> m_material;
	tl::unique_ptr<filament::Texture> m_texture;

	tl::vector<tl::unique_ref<filament::VertexBuffer>> m_vertexBuffers;
	tl::vector<tl::unique_ref<filament::IndexBuffer>> m_indexBuffers;
	tl::vector<tl::unique_ref<filament::MaterialInstance>> m_materialInstances;
	utils::Entity m_renderable;
};

}
