#pragma once

namespace psemek::wgpu::detail
{

	template <typename Derived>
	struct object
	{
		object() = default;

		object(object const & other)
			: ptr_(other.ptr_)
		{
			if (ptr_) Derived::reference(ptr_);
		}

		object(object && other)
			: ptr_(other.ptr_)
		{
			other.ptr_ = nullptr;
		}

		object & operator = (object const & other)
		{
			if (this == &other)
				return *this;
			reset();
			ptr_ = other.ptr_;
			if (ptr_) Derived::reference(ptr_);
			return *this;
		}

		object & operator = (object && other)
		{
			if (this == &other)
				return *this;
			reset();
			ptr_ = other.ptr_;
			other.ptr_ = nullptr;
			return *this;
		}

		~object()
		{
			reset();
		}

		void reset()
		{
			if (ptr_) Derived::release(ptr_);
			ptr_ = nullptr;
		}

		void * get() const { return ptr_; }

		explicit operator bool() const { return ptr_ != nullptr; }

		friend bool operator == (object const & o1, object const & o2)
		{
			return o1.ptr_ == o2.ptr_;
		}

	protected:
		object(void * ptr)
			: ptr_(ptr)
		{}

	private:
		void * ptr_ = nullptr;
	};

}
