#include "EntitySystem.h"
#include "ComponentSystem.h"

EntityId EntityId::s_invalidEntityId = EntityId();
EntitySystem EntitySystem::s_Instance = EntitySystem();

///////////////////////////////////////////////////////////////
EntitySystem& EntitySystem::GetInstance()
{
	return s_Instance;
}

EntityId EntitySystem::AddEntity()
{
	for (int i = nextInsertionIndex; i < entities.size(); i++)
	{
		const bool isAlive = entities[i].IsAlive();
		if (!isAlive)
		{
			EntityId newId(i, entities[i].myId.salt + 1);
			entities[i].myId = newId;

			nextInsertionIndex = i + 1;
			if (nextInsertionIndex >= std::numeric_limits<IndexType>::max())
			{
				//Go back to first valid index
				nextInsertionIndex = 1;
			}

			return newId;
		}
	}

	return EntityId();
}

Entity* EntitySystem::GetEntityByID(EntityId id)
{
	if (id.index == 0)
	{
		return nullptr;
	}

	if (entities[id.index].IsAlive() && entities[id.index].myId.salt == id.salt)
	{
		return &entities[id.index];
	}

	return nullptr;
}

bool EntitySystem::DestroyEntity(EntityId id)
{
	Entity* pEntity = GetEntityByID(id);
	if (pEntity != nullptr)
	{
		pEntity->myId.index = 0;
	
		for (int i = 0; i < systems.size(); i++)
		{
			systems[i]->RemoveEntity(id);
		}
		
		return true;
	}

	return false;
}

void EntitySystem::AddSystem(ComponentSystemBase& system)
{
	systems.push_back(&system);
}

void EntitySystem::Update(float deltaSeconds)
{
	for (int i = 0; i < systems.size(); i++)
	{
		systems[i]->Update(deltaSeconds);
	}
}
