#pragma once

class SystemBase;
class ECS
{
private:

	typedef std::unordered_map<std::uint8_t, std::vector<SystemBase*>>
		SystemsArrayMap;

	typedef std::unordered_map<size_t, ComponentBase*>
		ComponentTypeIdBaseMap;

	struct Record
	{
		Archetype* archetype;
		size_t index;
	};

	typedef std::unordered_map<size_t, Record> EntityArchetypeMap;

	typedef std::vector<Archetype*> ArchetypesArray;

	typedef std::unordered_map<size_t, ComponentMask> ComponentMasks;


public:
	explicit ECS();

	~ECS();

	void Update(const std::uint8_t layer, const std::uint32_t delta);

	void RegisterEntity(const uint32_t entityId);

	void DestroyEntity(const std::uint32_t entityId);

	template <class C>
	void RegisterComponent();

	template<class C, typename... Args>
	C* AddComponent(const uint32_t entityId, Args&&... args);

	template<class C>
	void RemoveComponent(const uint32_t entityId);

	template<class C>
	C* GetComponent(const uint32_t entityId);

	void RegisterSystem(const std::uint8_t& layer, SystemBase* system);

	void UnregisterSystem(const std::uint8_t& layer, SystemBase* system);

private:
	std::uint32_t entityIdCounter;

	SystemsArrayMap systems;

	EntityArchetypeMap entityArchetypeMap;

	EventBus eventBus_;

	ArchetypesArray archetypes;

	ComponentMasks componentMasks;

	ComponentTypeIdBaseMap componentMap;
};

class SystemBase
{
public:
	virtual ~SystemBase() {}

	virtual ComponentMask GetComponentMask() const = 0;

	virtual void Update(const std::uint32_t elapsedTime, Archetype* archetype) = 0;
};

class ECS;
template <class... Cs>
class System : public SystemBase
{
public:

	friend class ECS;
	typedef std::function<void(const std::uint32_t, const std::vector<uint32_t>&, Cs*...)> Func;

	System(ECS& ecs, const std::uint8_t& layer);

	virtual ComponentMask GetComponentMask() const override;

	void Action(Func func);
protected:

	template<std::size_t Index1, typename T, typename... Ts>
	std::enable_if_t<Index1 == sizeof...(Cs)>
		Update(const std::uint32_t elapsedMilliseconds,
			const ComponentMask& componentMask,
			const std::vector<uint32_t>& entityIds,
			T& t,
			Ts... ts);

	template<std::size_t Index1, typename T, typename... Ts>
	std::enable_if_t<Index1 != sizeof...(Cs)>
		Update(const std::uint32_t elapsedMilliseconds,
			const ComponentMask& componentMask,
			const std::vector<uint32_t>& entityIds,
			T& t,
			Ts... ts);

	virtual void Update(const std::uint32_t elapsedMilliseconds,
		Archetype* archetype) override;

	ECS& ecs_;
	ComponentMask componentMask_;
	Func func_;
	bool funcStatus_;
};
 Can you create an event bus system that can work with this? 