/* -----------------------------------------------------------------------------
	GSFramework
	Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */


		#include "core/cached_renderer_resource_factory.h"
		#include "log/log.h"

		using namespace GS;
		using namespace GS::Render;


//------------------------------------------------------------------------------
template <class T> static bool ResourceNameCompare(const T o, const String &name) { return String::Compare(o->name, name) == 0; }
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
template <class T> T CheckCachedResourceCommonSeq(const char *uri, const SharedList <T> *cache)
{
	if	(!cache)
		return NULL;

	String name(uri);
	name.FileCleanName();

	return ListFindEx(*cache, ResourceNameCompare <T>, name);
}
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
Geometry			*CachedRendererResourceFactory::LoadGeometry(const char *name, bool bypass_cache, Geometry *g)
{
	if	(!bypass_cache && !g)
		if	(Geometry *r = CheckCachedResourceCommonSeq <Geometry *> (name, &geometries))
			return r;
	Geometry *r = RendererResourceFactory::LoadGeometry(name, bypass_cache, g);
	if	(!bypass_cache && !g)
		if	(r)
			geometries.Add(r);
	return r;
}
Material			*CachedRendererResourceFactory::LoadMaterial(const char *name, bool bypass_cache, Material *m)
{
	if	(!bypass_cache && !m)
		if	(Material *r = CheckCachedResourceCommonSeq <Material *> (name, &materials))
			return r;
	Material *r = RendererResourceFactory::LoadMaterial(name, bypass_cache, m);
	if	(!bypass_cache && !m)
		if	(r)
			materials.Add(r);
	return r;
}
Texture				*CachedRendererResourceFactory::LoadTexture(const char *name, bool bypass_cache, Texture *t)
{
	if	(!bypass_cache && !t)
		if	(Texture *r = CheckCachedResourceCommonSeq <Texture *> (name, &textures))
			return r;
	Texture *r = RendererResourceFactory::LoadTexture(name, bypass_cache, t);
	if	(!bypass_cache && !t)
		if	(r)
			textures.Add(r);
	return r;
}
Shader				*CachedRendererResourceFactory::LoadShader(const char *name, bool bypass_cache, Shader *s)
{
	if	(!bypass_cache && !s)
		if	(Shader *r = CheckCachedResourceCommonSeq <Shader *> (name, &shaders))
			return r;
	Shader *r = RendererResourceFactory::LoadShader(name, bypass_cache, s);
	if	(!bypass_cache && !s)
		if	(r)
			shaders.Add(r);
	return r;
}
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
void				CachedRendererResourceFactory::ListCachedResources()
{
	ListForeachPtr(Geometry *, g, geometries)
		__LOG_V__ << "- " << g->name << " (refcount=" << g->GetRefCount() << ")\n";
	ListForeachPtr(Material *, m, materials)
		__LOG_V__ << "- " << m->name << " (refcount=" << m->GetRefCount() << ")\n";
	ListForeachPtr(Texture *, t, textures)
		__LOG_V__ << "- " << t->name << " (refcount=" << t->GetRefCount() << ")\n";
	ListForeachPtr(Shader *, s, shaders)
		__LOG_V__ << "- " << s->name << " (refcount=" << s->GetRefCount() << ")\n";
}
uint				CachedRendererResourceFactory::GetCachedResourceCount()
{
	uint count = 0;
	count += geometries.GetCount();
	count += materials.GetCount();
	count += textures.GetCount();
	count += shaders.GetCount();
	return count;
}
uint				CachedRendererResourceFactory::PurgeCache()
{
	uint purged = 0;
	forever
	{
		uint pass_purged = 0;
		pass_purged += PurgeSharedList(geometries);
		pass_purged += PurgeSharedList(materials);
		pass_purged += PurgeSharedList(textures);
		pass_purged += PurgeSharedList(shaders);
		if	(pass_purged == 0)
			break;

		purged += pass_purged;
	}
	return purged;
}
//------------------------------------------------------------------------------
