#include "ThreadCollection.h"

#include <vector>

bool ThreadCollection::add(std::unique_ptr<std::thread> thread)
{
	if (!mAccepting)
	{
		return false;
	}

	std::scoped_lock guard(mMutex);
	mThreads[thread->get_id()] = std::move(thread);

	return true;
}

void ThreadCollection::joinAndClearAll()
{
	mAccepting = false;
	std::vector<std::thread*> threads;
	{
		std::scoped_lock guard(mMutex);
		for (const auto& item : mThreads)
		{
			threads.push_back(item.second.get());
		}
	}

	for (auto thread : threads)
	{
		if (thread->joinable())
		{
			thread->join();
		}
	}

	std::scoped_lock guard(mMutex);
	mThreads.clear();
	mAccepting = true;
}

std::size_t ThreadCollection::size() const
{
	std::size_t size{ 0 };
	{
		std::scoped_lock guard(mMutex);
		size = mThreads.size();
	}
	return size;
}

void ThreadCollection::markForRemoval(std::thread::thread::id inputId)
{
	std::scoped_lock guard(mMutex);
	mMarkedForRemoval.push_back(inputId);
}

void ThreadCollection::removeMarked()
{
	std::scoped_lock guard(mMutex);
	for (const auto& id : mMarkedForRemoval)
	{
		_remove(id);
	}
	mMarkedForRemoval.clear();
}

void ThreadCollection::_remove(std::thread::thread::id inputId)
{
	if (auto const& it = mThreads.find(inputId); it != mThreads.end())
	{
		it->second->detach();
		mThreads.erase(it);
	}
}