#pragma once

#include <psemek/wgpu/detail/object.hpp>
#include <psemek/wgpu/chained_struct.hpp>
#include <psemek/math/interval.hpp>

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

namespace psemek::wgpu
{

	enum class address_mode : std::uint32_t
	{
		undefined     = 0x00000000,
		clamp_to_edge = 0x00000001,
		repeat        = 0x00000002,
		mirror_repeat = 0x00000003,
	};

	enum class filter_mode : std::uint32_t
	{
		undefined = 0x00000000,
		nearest   = 0x00000001,
		linear    = 0x00000002,
	};

	enum class mipmap_filter_mode : std::uint32_t
	{
		undefined = 0x00000000,
		nearest   = 0x00000001,
		linear    = 0x00000002,
	};

	enum class compare_function : std::uint32_t
	{
		undefined     = 0x00000000,
		never         = 0x00000001,
		less          = 0x00000002,
		equal         = 0x00000003,
		less_equal    = 0x00000004,
		greater       = 0x00000005,
		not_equal     = 0x00000006,
		greater_equal = 0x00000007,
		always        = 0x00000008,
	};

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

		struct descriptor {
			std::vector<chained_struct> chain = {};
			std::string label = {};
			address_mode address_mode_u;
			address_mode address_mode_v;
			address_mode address_mode_w;
			filter_mode mag_filter;
			filter_mode min_filter;
			mipmap_filter_mode mipmap_filter;
			math::interval<float> lod_clamp = {0.f, 255.f};
			compare_function compare = compare_function::undefined;
			std::uint16_t max_anisotropy = 1;
		};

		void set_label(std::string const & label);

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

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

		friend struct device;
	};

}
