#pragma once
#ifndef __MATERIAL_CACHE_H__
#define __MATERIAL_CACHE_H__

#include <map>

#include "smartptr.h"
#include "scene.h"
#include "TextureMap.h"
#include "SceneShadow.h"
#include "RTMaterial.h"

namespace VRUT
{
	class MaterialCache
	{

	protected:

		// texture map saved openGL textures (pixels data)
		TextureMap oglTextureMap;
		std::vector<RTMaterial> rtMaterials;
		RTMaterial defaultMaterial;
		RTMaterial enviromentMaterial;
		std::map<GEOMETRY_ID, RTMaterial> geometryTextRTMaterialsMap;

		std::vector< std::pair<wxFont, const_smart_pointer<Image> > > fontImageCache; //maps font name to index (many font materials may be based on the same font, that means using the same font texture)

		Vector4 GetCubeTexColor(const Ray& ray, unsigned int tw, unsigned int th, float * data, bool linear);

		/**
		*	count cube texture coords from reflected ray and return position in cube texture - supposed that
		*	that cube texture is saved in RGB format
		*	\param[in] ray - reflected ray
		*	\param[in] texWidth - texture width
		*	\param[in] texHeight - texture height
		*	\param[out] pos - position in cube texture data, for red color component - green is on pos + 1 and blue is
		*					  on pos + 2
		*/
		void GetCubeTexCoords(const Ray& ray, int tw, int th, size_t& pos);

		void TransformTexCoords(const RTMaterial &material, int texWidth, int texHeight, float & x, float & y) const;

		//Texturing coordinates are in image space
		Vector4 SampleTexture2DPoint(const wxImage* texture, int u, int v) const;
		Vector4 SampleTexture2DBilinear(const wxImage* texture, float u, float v) const;

	public:
		void GetTriangleTexCoords(const RayIntersectionInfo & rayInfo, const Vector2 * texCoord1, const Vector2 * texCoord2, const Vector2 * texCoord3, float & x, float & y);

		void GetSphereTexCoords(const RayIntersectionInfo & rayInfo, const Material * material, float & x, float & y);

		void GetMaterialDiffuseColor(const RTMaterial &material, const Ray & ray, const RayIntersectionInfo & rayInfo, float x, float y, float rayOffset, Vector4 & color, bool & usedTex,
			Vector4 & texColor);

		void GetEnvironmentColor(const Ray & ray, const RayIntersectionInfo & rayInfo, float rayOffset, Vector4 & color);

		void InvalidateImageCacheEntry(unsigned int index);
		void CacheEnvironmentalMap(SceneShadow * sceneShadow);

		Vector3 SampleNormalMap(const RTMaterial &material, float x, float y) const;

		//To be removed when font rendering will be made centralized
		//e.g. geometry & material of the font will actually be in scene graph
		void AddFontCacheImage(const_smart_pointer<Image> img, wxFont font);

		const Image* GetFontCacheImage(wxFont &font);

		void ResizeRTMaterials(MATERIAL_ID maxMid);

		RTMaterial *GetOrCreateRTMaterial(MATERIAL_ID mid, smart_pointer_v2<Scene> &scene, smart_pointer<Geometry> geo);
	};
}
#endif /* __MATERIAL_CACHE_H__ */
