#pragma once

#include <psemek/wgpu/detail/object.hpp>
#include <psemek/wgpu/chained_struct.hpp>
#include <psemek/wgpu/texture.hpp>
#include <psemek/wgpu/bind_group.hpp>
#include <psemek/wgpu/render_pipeline.hpp>
#include <psemek/wgpu/buffer.hpp>
#include <psemek/wgpu/render_bundle.hpp>

#include <string>
#include <vector>

namespace psemek::wgpu
{

	struct render_bundle_encoder
		: detail::object<render_bundle_encoder>
	{
		using detail::object<render_bundle_encoder>::object;

		struct descriptor
		{
			std::vector<chained_struct> chain = {};
			std::string label = {};
			std::vector<texture::format> color_formats;
			texture::format depth_stencil_format;
			std::uint32_t sample_count = 1;
			bool depth_read_only = false;
			bool stencil_read_only = true;
		};

		void set_pipeline(render_pipeline const & pipeline);
		void set_bind_group(std::uint32_t group_index, bind_group const & group, std::vector<std::uint32_t> const & dynamic_offsets);
		void set_vertex_buffer(std::uint32_t slot, buffer const & buffer, std::uint64_t offset, std::uint64_t size);
		void set_index_buffer(buffer const & buffer, index_format format, std::uint64_t offset, std::uint64_t size);
		void draw(std::uint32_t vertex_count, std::uint32_t instance_count, std::uint32_t first_vertex, std::uint32_t first_instance);
		void draw_indexed(std::uint32_t index_count, std::uint32_t instance_count, std::uint32_t first_index, std::uint32_t base_vertex, std::uint32_t first_instance);
		void draw_indirect(buffer const & indirect_buffer, std::uint64_t offset);
		void draw_indexed_indirect(buffer const & indirect_buffer, std::uint64_t offset);
		void insert_debug_marker(std::string_view marker_label);
		void push_debug_group(std::string_view group_label);
		void pop_debug_group();
		render_bundle finish(render_bundle::descriptor const & desc);
		void set_label(std::string const & label);

		static void reference(void * ptr);
		static void release(void * ptr);

	private:
		explicit render_bundle_encoder(void * ptr)
			: detail::object<render_bundle_encoder>(ptr)
		{}

		friend struct device;
	};

}
