#pragma once

#include <psemek/wgpu/chained_struct.hpp>
#include <psemek/wgpu/command_buffer.hpp>
#include <psemek/wgpu/buffer.hpp>
#include <psemek/wgpu/texture.hpp>
#include <psemek/wgpu/image_copy.hpp>
#include <psemek/wgpu/callback_mode.hpp>
#include <psemek/wgpu/detail/object.hpp>
#include <psemek/util/span.hpp>

#include <string>
#include <vector>
#include <cstdint>
#include <functional>

namespace psemek::wgpu
{

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

		struct descriptor
		{
			std::vector<chained_struct> chain = {};
			std::string label = {};
		};

		enum class work_done_status : std::uint32_t
		{
			success          = 0x00000001,
			instance_dropped = 0x00000002,
			error            = 0x00000003,
			unknown          = 0x00000004,
		};

		using work_done_callback = std::function<void(work_done_status)>;

		void submit(std::vector<command_buffer> const & commands);
		void write_buffer(buffer const & buffer, std::uint64_t offset, util::span<char const> data);
		void write_texture(texel_copy_texture_info const & dest, util::span<char const> data, texel_copy_buffer_layout const & data_layout, math::vector<std::uint32_t, 3> const & write_size);
		void on_submitted_work_done(callback_mode mode, work_done_callback const & callback);
		void set_label(std::string const & label);

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

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

		friend struct device;
	};

}
