#pragma once

#include <vector>
#include "../Interfaces/IServiceLocator.h"


class k_ServiceLocator
	: public IServiceLocator
{
public:
	k_ServiceLocator()
		: mb_Initialized(false)
	{
	}

	virtual ~k_ServiceLocator()
	{
		this->DeinitializeServices();
	}

	void* k_ServiceLocator::QueryInterface(const GUID& ar_InterfaceGuid)
	{
		if (ar_InterfaceGuid == __uuidof(IServiceLocator)) 
			return static_cast<IServiceLocator*>(this);
		else
		{
			std::vector<IService*>::iterator lk_Iter = mk_ServiceList.begin();
			for (; lk_Iter != mk_ServiceList.end(); ++lk_Iter)
			{
				void* lv_Value_ = (*lk_Iter)->QueryInterface(ar_InterfaceGuid);
				if (lv_Value_ != NULL) 
					return lv_Value_;
			}
		}

		return NULL; 
	}

	void k_ServiceLocator::AddService(IService* ar_ServiceObject_)
	{
		if (ar_ServiceObject_== NULL || this->TrySearchService(ar_ServiceObject_))
			return;

		if (mb_Initialized)
			ar_ServiceObject_->Initialize(*this);

		mk_ServiceList.push_back(ar_ServiceObject_);
	}

	void k_ServiceLocator::RemoveService(IService* ar_ServiceObject_)
	{
		if (ar_ServiceObject_== NULL)
			return;

		std::vector<IService*>::iterator lk_Iter = mk_ServiceList.begin();
		for (; lk_Iter != mk_ServiceList.end(); ++lk_Iter)
			if ((*lk_Iter) == ar_ServiceObject_)
			{
				if (mb_Initialized || (*lk_Iter)->get_IsInitialized())
					(*lk_Iter)->Deinitialize();
				delete *lk_Iter;				
				mk_ServiceList.erase(lk_Iter);
				return;
			}
	}

	void k_ServiceLocator::InitializeServices()
	{
		std::vector<IService*>::iterator lk_Iter = mk_ServiceList.begin();
		for (; lk_Iter != mk_ServiceList.end(); ++lk_Iter)
			if (!(*lk_Iter)->get_IsInitialized())
				(*lk_Iter)->Initialize(*this);
		mb_Initialized = true;
	}

	void k_ServiceLocator::DeinitializeServices()
	{
		std::vector<IService*>::iterator lk_Iter = mk_ServiceList.begin();
		for (; lk_Iter != mk_ServiceList.end(); ++lk_Iter)
			if ((*lk_Iter)->get_IsInitialized())
				(*lk_Iter)->Deinitialize();

		while (mk_ServiceList.empty())
		{
			delete mk_ServiceList.front();				
			mk_ServiceList.erase(mk_ServiceList.begin());
		}

		mb_Initialized = false;
	}

protected:
	IService* k_ServiceLocator::TrySearchService(IService* ar_ServiceObject_)
	{
		std::vector<IService*>::iterator lk_Iter = mk_ServiceList.begin();
		for (; lk_Iter != mk_ServiceList.end(); ++lk_Iter)
			if ((*lk_Iter) == ar_ServiceObject_)
				return *lk_Iter;
		return NULL;
	}

private:
	std::vector<IService*> mk_ServiceList;
	bool mb_Initialized;
};
