#include "ShaderSystem.h"

ShaderSystem::ShaderSystem(IDirect3DDevice9* inDevice)
	: Device(inDevice)
{

}


ShaderSystem::~ShaderSystem()
{
	while (!AnnotationHandlerList.empty())
	{
		delete AnnotationHandlerList.begin()->second;
		AnnotationHandlerList.erase(AnnotationHandlerList.begin());
	}

	while (!SemanticHandlerList.empty())
	{
		delete SemanticHandlerList.begin()->second;
		SemanticHandlerList.erase(SemanticHandlerList.begin());
	}

	while (!CallbackHandlerList.empty())
	{
		delete CallbackHandlerList.begin()->second;
		CallbackHandlerList.erase(CallbackHandlerList.begin());
	}

	while (!ShaderList.empty())
	{
		delete ShaderList.begin()->second;
		ShaderList.erase(ShaderList.begin());
	}
}


bool ShaderSystem::AddAnnotationHandler(IAnnotationHandler* inAnnotationHandler)
{
	if (!inAnnotationHandler)
		return false;

	if (this->get_AnnotationHandler(inAnnotationHandler->get_Name()))
		return false;

	AnnotationHandlerList[inAnnotationHandler->get_Name()] = inAnnotationHandler;

	return true;
}


bool ShaderSystem::RemoveAnnotationHandler(IAnnotationHandler* inAnnotationHandler)
{
	if (!inAnnotationHandler)
		return false;

	std::map<std::string, IAnnotationHandler*>::iterator Iterator = AnnotationHandlerList.find(inAnnotationHandler->get_Name());
	if (Iterator != AnnotationHandlerList.end())
	{
		delete Iterator->second;
		AnnotationHandlerList.erase(Iterator);
		return true;
	}

	return false;
}


bool ShaderSystem::RemoveAnnotationHandler(const std::string& inAnnotationHandlerName)
{
	return this->RemoveAnnotationHandler(this->get_AnnotationHandler(inAnnotationHandlerName));
}


IAnnotationHandler* ShaderSystem::get_AnnotationHandler(const std::string& inAnnotationHandlerName) const
{
	std::map<std::string, IAnnotationHandler*>::const_iterator Iterator = AnnotationHandlerList.find(inAnnotationHandlerName);
	if (Iterator != AnnotationHandlerList.end())
		return Iterator->second;
	return NULL;
}


bool ShaderSystem::AddCallbackHandler(ICallbackHandler* inCallbackHandler)
{
	if (!inCallbackHandler)
		return false;

	if (this->get_CallbackHandler(inCallbackHandler->get_Name()))
		return false;

	CallbackHandlerList[inCallbackHandler->get_Name()] = inCallbackHandler;

	return true;
}


bool ShaderSystem::RemoveCallbackHandler(ICallbackHandler* inCallbackHandler)
{
	if (!inCallbackHandler)
		return false;

	std::map<std::string, ICallbackHandler*>::iterator Iterator = CallbackHandlerList.find(inCallbackHandler->get_Name());
	if (Iterator != CallbackHandlerList.end())
	{
		delete Iterator->second;
		CallbackHandlerList.erase(Iterator);
		return true;
	}

	return false;
}


bool ShaderSystem::RemoveCallbackHandler(const std::string& inCallbackHandlerName)
{
	return this->RemoveCallbackHandler(this->get_CallbackHandler(inCallbackHandlerName));
}


ICallbackHandler* ShaderSystem::get_CallbackHandler(const std::string& inCallbackHandlerName) const
{
	std::map<std::string, ICallbackHandler*>::const_iterator Iterator = CallbackHandlerList.find(inCallbackHandlerName);
	if (Iterator != CallbackHandlerList.end())
		return Iterator->second;
	return NULL;
}


bool ShaderSystem::AddSemanticHandler(ISemanticHandler* inSemanticHandler)
{
	if (!inSemanticHandler)
		return false;

	if (this->get_SemanticHandler(inSemanticHandler->get_Name()))
		return false;

	SemanticHandlerList[inSemanticHandler->get_Name()] = inSemanticHandler;

	return true;
}


bool ShaderSystem::RemoveSemanticHandler(ISemanticHandler* inSemanticHandler)
{
	if (!inSemanticHandler)
		return false;

	std::map<std::string, ISemanticHandler*>::iterator Iterator = SemanticHandlerList.find(inSemanticHandler->get_Name());
	if (Iterator != SemanticHandlerList.end())
	{
		delete Iterator->second;
		SemanticHandlerList.erase(Iterator);
		return true;
	}

	return false;
}


bool ShaderSystem::RemoveSemanticHandler(const std::string& inSemanticHandlerName)
{
	return this->RemoveSemanticHandler(this->get_SemanticHandler(inSemanticHandlerName));
}


ISemanticHandler* ShaderSystem::get_SemanticHandler(const std::string& inSemanticHandlerName) const
{
	std::map<std::string, ISemanticHandler*>::const_iterator Iterator = SemanticHandlerList.find(inSemanticHandlerName);
	if (Iterator != SemanticHandlerList.end())
		return Iterator->second;
	return NULL;
}


IShader* ShaderSystem::CreateShader(const std::string& inShaderName, const std::string& inShaderCode)
{
	Shader* NewShader = new Shader(Device, this, inShaderName, inShaderCode, "");
	this->AddShader(NewShader);
	this->FillShaderWithHandlers(NewShader);
	return NewShader;
}


IShader* ShaderSystem::LoadShader(const std::string& inShaderName, const std::string& inShaderFileName)
{
	Shader* NewShader = new Shader(Device, this, inShaderName, "", inShaderFileName);
	this->AddShader(NewShader);
	this->FillShaderWithHandlers(NewShader);
	return NewShader;
}


IShader* ShaderSystem::get_Shader(const std::string& inShaderName) const
{
	std::map<std::string, IShader*>::const_iterator Iterator = ShaderList.find(inShaderName);
	if (Iterator != ShaderList.end())
		return Iterator->second;
	return NULL;
}


bool ShaderSystem::RemoveShader(IShader* inShader)
{
	if (!inShader)
		return false;

	std::map<std::string, IShader*>::iterator Iterator = ShaderList.find(inShader->get_Name());
	if (Iterator != ShaderList.end())
	{
		delete Iterator->second;
		ShaderList.erase(Iterator);
		return true;
	}

	return false;
}


bool ShaderSystem::RemoveShader(const std::string& inShaderName)
{
	return this->RemoveShader(this->get_Shader(inShaderName));
}


void ShaderSystem::Refresh(IDirect3DDevice9* inDevice)
{
	std::map<std::string, IShader*>::iterator Iterator = ShaderList.begin();
	while (Iterator != ShaderList.end())
		Iterator->second->Refresh(inDevice);
}


bool ShaderSystem::AddShader(Shader* inShader)
{
	if (!inShader)
		return false;

	if (this->get_Shader(inShader->get_Name()))
		return false;

	ShaderList[inShader->get_Name()] = inShader;

	return true;
}


void ShaderSystem::FillShaderWithHandlers(Shader* inShader)
{
	std::map<std::string, IAnnotationHandler*>::iterator AnnotationIterator = AnnotationHandlerList.begin();
	while (AnnotationIterator != AnnotationHandlerList.end())
	{
		inShader->AddSystemAnnotationHandler(AnnotationIterator->second);
		AnnotationIterator++;
	}

	std::map<std::string, ICallbackHandler*>::iterator CallbackIterator = CallbackHandlerList.begin();
	while (CallbackIterator != CallbackHandlerList.end())
	{
		inShader->AddSystemCallbackHandler(CallbackIterator->second);
		CallbackIterator++;
	}


	std::map<std::string, ISemanticHandler*>::iterator SemanticIterator = SemanticHandlerList.begin();
	while (SemanticIterator != SemanticHandlerList.end())
	{
		inShader->AddSystemSemanticHandler(SemanticIterator->second);
		SemanticIterator++;
	}
}