#pragma once

#include <psemek/util/uuid.hpp>
#include <psemek/util/hash.hpp>

namespace psemek::ecs::detail
{

	template <bool With>
	struct ordered_component_hasher
	{
		std::uint64_t result = 0xb6113227befa663bull;

		void operator()(util::uuid const & uuid)
		{
			auto hash = std::hash<util::uuid>{}(uuid);
			if (!With)
				hash = ~hash;

			util::hash_combine(result, hash);
		}
	};

	template <bool With, typename UUIDs>
	std::uint64_t ordered_component_hash(UUIDs const & uuids)
	{
		ordered_component_hasher<With> hasher;
		for (auto const & uuid : uuids)
			hasher(uuid);
		return hasher.result;
	}

	template <typename WithUUIDs, typename WithoutUUIDs>
	std::uint64_t ordered_component_hash(WithUUIDs const & with_uuids, WithoutUUIDs const & without_uuids)
	{
		return ordered_component_hash<true>(with_uuids) ^ ordered_component_hash<false>(without_uuids);
	}

}
