#include <psemek/wgpu/buffer.hpp>
#include <psemek/wgpu/detail/string_view.hpp>
#include <psemek/wgpu/external/webgpu.h>

#include <memory>

namespace psemek::wgpu
{

	void buffer::destroy()
	{
		wgpuBufferDestroy((WGPUBuffer)get());
	}

	std::uint64_t buffer::get_size() const
	{
		return wgpuBufferGetSize((WGPUBuffer)get());
	}

	buffer::usage buffer::get_usage() const
	{
		return (usage)wgpuBufferGetUsage((WGPUBuffer)get());
	}

	buffer::map_state buffer::get_map_state() const
	{
		return (map_state)wgpuBufferGetMapState((WGPUBuffer)get());
	}

	void const * buffer::get_const_mapped_range(std::size_t offset, std::size_t size) const
	{
		return wgpuBufferGetConstMappedRange((WGPUBuffer)get(), offset, size);
	}

	void * buffer::get_mapped_range(std::size_t offset, std::size_t size)
	{
		return wgpuBufferGetMappedRange((WGPUBuffer)get(), offset, size);
	}

	void buffer::map_async(callback_mode mode, map_mode flags, std::size_t offset, std::size_t size, map_callback const & callback)
	{
		WGPUBufferMapCallbackInfo callback_info = {};
		callback_info.mode = (WGPUCallbackMode)mode;
		callback_info.callback = [](WGPUMapAsyncStatus status, WGPUStringView message, void * userdata, void *)
		{
			std::unique_ptr<map_callback> callback((map_callback *)userdata);
			if (*callback) (*callback)((map_async_status)status, std::string_view(message.data, message.length));
		};
		callback_info.userdata1 = new map_callback(callback);

		wgpuBufferMapAsync((WGPUBuffer)get(), (WGPUMapMode)flags, offset, size, callback_info);
	}

	void buffer::unmap()
	{
		wgpuBufferUnmap((WGPUBuffer)get());
	}

	void buffer::set_label(std::string const & label)
	{
		wgpuBufferSetLabel((WGPUBuffer)get(), detail::to_string_view(label));
	}

	void buffer::reference(void * ptr)
	{
		wgpuBufferAddRef((WGPUBuffer)ptr);
	}

	void buffer::release(void * ptr)
	{
		wgpuBufferRelease((WGPUBuffer)ptr);
	}

}
