#include "TextureMap.h"
#include "smartptr.h"
#include "kernel.h"
#include "scenemanager.h"

using namespace VRUT;

TextureMap::TextureMap()
{
}

TextureMap::~TextureMap()
{
	strings.clear();
	data.clear();
}

void TextureMap::Add(const wxString& str, float * d, size_t arraySize)
{
	strings.push_back(str);
	data.push_back(d);
	arraySizes.push_back(arraySize);
}

float * TextureMap::GetData(const wxString& str, size_t & arraySize)
{
	for (size_t i = 0; i < strings.size(); ++i)
	{
		if (str == strings[i])
		{
			arraySize = arraySizes[i];
			return data[i];
		}
	}
	arraySize = 0;
	return nullptr;
}

void TextureMap::CopyDDSTexDataToRayTracerTexData(const Material *mat)
{
#ifndef VRUT_HPC
#if USEOPENGL
	// if material exists and has some texture name defined
	if (mat && !mat->imageName.IsEmpty())
	{
		size_t size;
		//	if for texture name is texture not loaded and saved
		if (GetData(mat->imageName, size) == nullptr)
		{
			//	lock access to KERNEL scene manager and get image
			const_smart_pointer<Image> img = KERNEL->sceneManager->GetImage(mat->imageName, false);
			if (!img)
				return;
			// if image is DDS type load and save it to oglTextureMap
			if (img->GetType() == Image::DDSIMAGE)
			{
				int texWidth = img->GetWidth();
				int texHeight = img->GetHeight();
				// if image is cube type
				if (img->IsCube())
				{
					GLfloat * data = new GLfloat[18 * texWidth * texHeight];
					// call building texture in OpenGL and bind it
					GLuint tex_object;
					glGenTextures(1, &tex_object);
					glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
					img->UpdateOglTexture(tex_object, Image::TEXCUBE, true);
					// count offset for every cube size in cube texture where will be data saved
					unsigned int offset = texWidth * texHeight * 3;
					// copy texels from OpenGL texture to data
					glGetTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGB, GL_FLOAT, data);
					glGetTexImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGB, GL_FLOAT, data + offset);
					glGetTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGB, GL_FLOAT, data + 2 * offset);
					glGetTexImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGB, GL_FLOAT, data + 3 * offset);
					glGetTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGB, GL_FLOAT, data + 4 * offset);
					glGetTexImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGB, GL_FLOAT, data + 5 * offset);
					// add texture to oglTextureMap
					Add(mat->imageName, data, 18 * texWidth * texHeight);
					glDeleteTextures(1, &tex_object);
				}
				else
				{
					GLfloat * data = new GLfloat[3 * texWidth * texHeight];
					// call building texture in OpenGL and bind it
					GLuint tex_object;
					glGenTextures(1, &tex_object);
					glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
					img->UpdateOglTexture(tex_object, Image::TEX2D, false);
					// copy texels from OpenGL texture to data
					glGetTexImage(GL_TEXTURE_2D, 0, GL_RGB, GL_FLOAT, data);
					// add texture to oglTextureMap
					Add(mat->imageName, data, 3 * texWidth * texHeight);
					glDeleteTextures(1, &tex_object);
				}
			}
		}
	}
#endif
#endif //VRUT_HPC
}
