#pragma once
#include "../../stdafx.h"
#include "../glLibLocals.h"
#include "../glLibError.h"
#include "glLibTexture.h"

namespace glLib { namespace Texture {

//TODO: multiple rects for different faces.
class texture_cube : public glLibInternal_texture {
	/*friend void glLibInternal_update_cubemap( //TODO: const correct
		Texture::texture_cube* cubemap, const View::view_3D* cubemap_view,
		double x, double y, double z,
		void(*draw_reflectees)(void),
		const bool update[6]);*/
	//Update reference(...) when changing attributes
	public:
		unsigned long x, width;
		unsigned long y, height;
		unsigned long size[2];
		glLibFlagTextureEdge edge;
		unsigned long num_texels;
		unsigned long rect[4];
	private:
		SDL_Surface *data_face_negx_surf1,*data_face_posx_surf1;
		SDL_Surface *data_face_negx_surf2,*data_face_posx_surf2;
		SDL_Surface *data_face_negy_surf1,*data_face_posy_surf1;
		SDL_Surface *data_face_negy_surf2,*data_face_posy_surf2;
		SDL_Surface *data_face_negz_surf1,*data_face_posz_surf1;
		SDL_Surface *data_face_negz_surf2,*data_face_posz_surf2;
		Uint8 *data_face_negx_uint8, *data_face_posx_uint8;
		Uint8 *data_face_negy_uint8, *data_face_posy_uint8;
		Uint8 *data_face_negz_uint8, *data_face_posz_uint8;
		float *data_face_negx_float32, *data_face_posx_float32;
		float *data_face_negy_float32, *data_face_posy_float32;
		float *data_face_negz_float32, *data_face_posz_float32;
		GLint data_type;

	public:
		//Constructors
		texture_cube(void);
		template <                    typename type_rect, typename type_filter_min, typename type_filter_mag                        > texture_cube(                     const type_rect flag_rect, const glLibFlagTextureFormat format, const type_filter_min flag_filter_min, const type_filter_mag flag_filter_mag,                               int precision=8) {
			glLibInternal_make((int)(-1),flag_rect, format, flag_filter_min, flag_filter_mag, (int)(-1), precision);
			contains_data = true;
		}
		template <typename type_data, typename type_rect, typename type_filter_min, typename type_filter_mag                        > texture_cube(const type_data data, const type_rect flag_rect, const glLibFlagTextureFormat format, const type_filter_min flag_filter_min, const type_filter_mag flag_filter_mag,                               int precision=8) {
			glLibInternal_make(data,flag_rect, format, flag_filter_min, flag_filter_mag, (int)(-1), precision);
			contains_data = true;
		}
		template <                    typename type_rect, typename type_filter_min, typename type_filter_mag, typename type_colorkey> texture_cube(                      const type_rect flag_rect, const glLibFlagTextureFormat format, const type_filter_min flag_filter_min, const type_filter_mag flag_filter_mag, const type_colorkey colorkey, int precision=8) {
			glLibInternal_make((int)(-1),flag_rect, format, flag_filter_min, flag_filter_mag, colorkey, precision);
			contains_data = true;
		}
		template <typename type_data, typename type_rect, typename type_filter_min, typename type_filter_mag, typename type_colorkey> texture_cube(const type_data data, const type_rect flag_rect, const glLibFlagTextureFormat format, const type_filter_min flag_filter_min, const type_filter_mag flag_filter_mag, const type_colorkey colorkey, int precision=8) {
			glLibInternal_make(data,flag_rect, format, flag_filter_min, flag_filter_mag, colorkey, precision);
			contains_data = true;
		}
	public:    ~texture_cube(void);

	public:    texture_cube& reference(const texture_cube* ref_tex);

	public:    void fastest(void);
	public:    void nicest(void);

	public:    void set_edge(const glLibFlagTextureEdge value);

	public:    void load_data(void);
	private:   template <typename T> void glLibInternal_load_data(GLenum target, GLenum type, const T data) {
			glTexImage2D(target,
				0,enum_texture_format_internal,
				width,height,
				0,enum_texture_format,type,data);
		}
	private:   inline void glLibInternal_update_mipmap(const glLibFlagFilter filtering) {
			throw error("Not implemented!");
		}

	private:
		void glLibInternal_make_init(void);

		void glLibInternal_make_set_rect_data_from(const unsigned short rect[]);
		void glLibInternal_make_set_rect_data_from(const SDL_Surface* surf);
		void glLibInternal_make_check_rect(const SDL_Surface* surf, string addendum);

		void glLibInternal_make_rects_load_surfaces(char face_num, const Uint8* data1, const float* data2, const double* data3, const SDL_Surface* data4, const char* file_path1, const glLibFlag* rect_flag, const unsigned short rect_data[4]) {
			/*if      (data1 != NULL) { //Uint32
				#ifdef GLLIB_ERROR_MODE_REPORT_ERRORS
				glLibInternal_make_check_rect_infer(rect_flag,"Uint32");
				#endif
				glLibInternal_make_set_rect_data_from(rect_data);
			}
			else if (data2 != NULL) { //Float32
				#ifdef GLLIB_ERROR_MODE_REPORT_ERRORS
				glLibInternal_make_check_rect_infer(rect_flag,"Float32");
				#endif
				glLibInternal_make_set_rect_data_from(rect_data);
			}
			else if (data3 != NULL) { //Double
				#ifdef GLLIB_ERROR_MODE_REPORT_ERRORS
				glLibInternal_make_check_rect_infer(rect_flag,"Double");
				#endif
				glLibInternal_make_set_rect_data_from(rect_data);
			}
			else if (data4 != NULL) { //SDL_Surface
				if (*rect_flag==GLLIB_ALL) {
					glLibInternal_make_set_rect_data_from(data4);
				}
				else {
					glLibInternal_make_set_rect_data_from(rect_data);

					#ifdef GLLIB_ERROR_MODE_REPORT_ERRORS
					glLibInternal_make_check_rect(data4," passed to this texture");
					#endif
				}
			}
			else if (file_path1 != NULL) { //char*
				switch (face_num) {
					case 0: data_face_negx_surf1 = glLibInternal_load_surface(file_path1); break;
					case 1: data_face_posx_surf1 = glLibInternal_load_surface(file_path1); break;
					case 2: data_face_negy_surf1 = glLibInternal_load_surface(file_path1); break;
					case 3: data_face_posy_surf1 = glLibInternal_load_surface(file_path1); break;
					case 4: data_face_negz_surf1 = glLibInternal_load_surface(file_path1); break;
					case 5: data_face_posz_surf1 = glLibInternal_load_surface(file_path1); break;
				}

				if (*rect_flag==GLLIB_ALL) {
					switch (face_num) {
						case 0: glLibInternal_make_set_rect_data_from(data_face_negx_surf1); break;
						case 1: glLibInternal_make_set_rect_data_from(data_face_posx_surf1); break;
						case 2: glLibInternal_make_set_rect_data_from(data_face_negy_surf1); break;
						case 3: glLibInternal_make_set_rect_data_from(data_face_posy_surf1); break;
						case 4: glLibInternal_make_set_rect_data_from(data_face_negz_surf1); break;
						case 5: glLibInternal_make_set_rect_data_from(data_face_posz_surf1); break;
					}
				}
				else {
					glLibInternal_make_set_rect_data_from(rect_data);

					#ifdef GLLIB_ERROR_MODE_REPORT_ERRORS
					switch (face_num) {
						case 0: glLibInternal_make_check_rect( data_face_negx_surf1, string(" loaded from file \"")+file_path1+"\"" ); break;
						case 1: glLibInternal_make_check_rect( data_face_posx_surf1, string(" loaded from file \"")+file_path1+"\"" ); break;
						case 2: glLibInternal_make_check_rect( data_face_negy_surf1, string(" loaded from file \"")+file_path1+"\"" ); break;
						case 3: glLibInternal_make_check_rect( data_face_posy_surf1, string(" loaded from file \"")+file_path1+"\"" ); break;
						case 4: glLibInternal_make_check_rect( data_face_negz_surf1, string(" loaded from file \"")+file_path1+"\"" ); break;
						case 5: glLibInternal_make_check_rect( data_face_posz_surf1, string(" loaded from file \"")+file_path1+"\"" ); break;
					}
					#endif
				}
			}
			else { //Blank texture
				#ifdef GLLIB_ERROR_MODE_REPORT_ERRORS
				if (rect_flag!=NULL) {
					throw GLLIB_ERROR_TYPE_ERROR("For blank textures, the data size cannot be inferred!  Pass a rectangle instead.");
				}
				#endif
				glLibInternal_make_set_rect_data_from(rect_data);
			}*/
		}

		//TODO: const correct all this.
		#ifdef GLLIB_ERROR_MODE_REPORT_ERRORS //all seven functions in this #ifdef throw errors
		void glLibInternal_make_rects_load_surfaces(char face_num, Uint8*            data, const glLibFlag rect_flag) {
			glLibInternal_make_throw_rect_infer("Uint32");
		}
		void glLibInternal_make_rects_load_surfaces(char face_num, float*            data, const glLibFlag rect_flag) {
			glLibInternal_make_throw_rect_infer("Float32");
		}
		void glLibInternal_make_rects_load_surfaces(char face_num, double*           data, const glLibFlag rect_flag) {
			glLibInternal_make_throw_rect_infer("Double");
		}
		void glLibInternal_make_rects_load_surfaces(char face_num, Uint8**           data, const glLibFlag rect_flag) {
			glLibInternal_make_throw_rect_infer("Uint32");
		}
		void glLibInternal_make_rects_load_surfaces(char face_num, float**           data, const glLibFlag rect_flag) {
			glLibInternal_make_throw_rect_infer("Float32");
		}
		void glLibInternal_make_rects_load_surfaces(char face_num, double**          data, const glLibFlag rect_flag) {
			glLibInternal_make_throw_rect_infer("Double");
		}
		void glLibInternal_make_rects_load_surfaces(char face_num, int          null_data, const glLibFlag rect_flag) {
			throw error("For blank textures, the data size cannot be inferred!  Pass a rectangle instead.");
		}
		#endif
		void glLibInternal_make_rects_load_surfaces(char face_num, Uint8*            data, const unsigned short rect_data[4]) {
			glLibInternal_make_set_rect_data_from(rect_data);
		}
		void glLibInternal_make_rects_load_surfaces(char face_num, float*            data, const unsigned short rect_data[4]) {
			glLibInternal_make_set_rect_data_from(rect_data);
		}
		void glLibInternal_make_rects_load_surfaces(char face_num, double*           data, const unsigned short rect_data[4]) {
			glLibInternal_make_set_rect_data_from(rect_data);
		}
		void glLibInternal_make_rects_load_surfaces(char face_num, Uint8**           data, const unsigned short rect_data[4]) {
			glLibInternal_make_set_rect_data_from(rect_data);
		}
		void glLibInternal_make_rects_load_surfaces(char face_num, float**           data, const unsigned short rect_data[4]) {
			glLibInternal_make_set_rect_data_from(rect_data);
		}
		void glLibInternal_make_rects_load_surfaces(char face_num, double**          data, const unsigned short rect_data[4]) {
			glLibInternal_make_set_rect_data_from(rect_data);
		}
		void glLibInternal_make_rects_load_surfaces(char face_num, int          null_data, const unsigned short rect_data[4]) {
			glLibInternal_make_set_rect_data_from(rect_data);
		}

		void glLibInternal_make_rects_load_surfaces(char face_num, SDL_Surface*      data, const glLibFlag rect_flag) {
			if (rect_flag==GLLIB_ALL) {
				glLibInternal_make_set_rect_data_from(data);
			}
			#ifdef GLLIB_ERROR_MODE_REPORT_ERRORS
			else throw error("Invalid rect flag!  Must be \"GLLIB_ALL\".");
			#endif
		}
		void glLibInternal_make_rects_load_surfaces(char face_num, SDL_Surface*      data, const unsigned short rect_data[4]) {
			glLibInternal_make_set_rect_data_from(rect_data);

			#ifdef GLLIB_ERROR_MODE_REPORT_ERRORS
			glLibInternal_make_check_rect(data," passed to this texture");
			#endif
		}

		void glLibInternal_make_rects_load_surfaces(char face_num, const char*  path_data, const glLibFlag rect_flag) {
			data_face_negx_surf1 = data_face_posx_surf1 = data_face_negy_surf1 = data_face_posy_surf1 = data_face_negz_surf1 = data_face_posz_surf1 \
				= glLibInternal_load_surface(path_data);

			if (rect_flag==GLLIB_ALL) {
				glLibInternal_make_set_rect_data_from(data_face_negx_surf1);
			}
			#ifdef GLLIB_ERROR_MODE_REPORT_ERRORS
			else throw error("Invalid rect flag!  Must be \"GLLIB_ALL\".");
			#endif
		}
		void glLibInternal_make_rects_load_surfaces(char face_num, const char*  path_data, const unsigned short rect_data[4]) {
			data_face_negx_surf1 = data_face_posx_surf1 = data_face_negy_surf1 = data_face_posy_surf1 = data_face_negz_surf1 = data_face_posz_surf1 \
				= glLibInternal_load_surface(path_data);

			glLibInternal_make_set_rect_data_from(rect_data);

			#ifdef GLLIB_ERROR_MODE_REPORT_ERRORS
			//Check that the rect is reasonable
			glLibInternal_make_check_rect( data_face_negx_surf1, string(" loaded from file \"")+path_data+"\"" );
			#endif
		}

		void glLibInternal_make_rects_load_surfaces(char face_num, SDL_Surface**     data, const glLibFlag rect_flag) {
			if (rect_flag==GLLIB_ALL) {
				glLibInternal_make_set_rect_data_from(data[0]);
			}
			#ifdef GLLIB_ERROR_MODE_REPORT_ERRORS
			else throw error("Invalid rect flag!  Must be \"GLLIB_ALL\".");

			for (char i=1;i<6;++i) {
				if ( (data[0]->w!=data[i]->w) || (data[0]->h!=data[i]->h) ) {
					throw error("Surface sizes do not match; rect dimensions cannot be inferred!");
				}
			}
			#endif
		}
		void glLibInternal_make_rects_load_surfaces(char face_num, SDL_Surface**     data, const unsigned short rect_data[4]) {
			glLibInternal_make_set_rect_data_from(rect_data);

			#ifdef GLLIB_ERROR_MODE_REPORT_ERRORS
			for (char i=1;i<6;++i) glLibInternal_make_check_rect(data[i]," passed to this texture");
			#endif
		}

		void glLibInternal_make_rects_load_surfaces(char face_num, const char** path_data, const glLibFlag rect_flag) {
			data_face_negx_surf1 = glLibInternal_load_surface(path_data[0]);
			data_face_posx_surf1 = glLibInternal_load_surface(path_data[1]);
			data_face_negy_surf1 = glLibInternal_load_surface(path_data[2]);
			data_face_posy_surf1 = glLibInternal_load_surface(path_data[3]);
			data_face_negz_surf1 = glLibInternal_load_surface(path_data[4]);
			data_face_posz_surf1 = glLibInternal_load_surface(path_data[5]);

			if (rect_flag==GLLIB_ALL) {
				glLibInternal_make_set_rect_data_from(data_face_negx_surf1);
			}
			#ifdef GLLIB_ERROR_MODE_REPORT_ERRORS
			else throw error("Invalid rect flag!  Must be \"GLLIB_ALL\".");

			SDL_Surface* data[6] = { data_face_negx_surf1,data_face_posx_surf1, data_face_negy_surf1,data_face_posy_surf1, data_face_negz_surf1,data_face_posz_surf1 };
			for (char i=1;i<6;++i) {
				if ( (data[0]->w!=data[i]->w) || (data[0]->h!=data[i]->h) ) {
					throw error("Surface sizes do not match; rect dimensions cannot be inferred!");
				}
			}
			#endif
		}
		void glLibInternal_make_rects_load_surfaces(char face_num, const char** path_data, const unsigned short rect_data[4]) {
			data_face_negx_surf1 = glLibInternal_load_surface(path_data[0]);
			data_face_posx_surf1 = glLibInternal_load_surface(path_data[1]);
			data_face_negy_surf1 = glLibInternal_load_surface(path_data[2]);
			data_face_posy_surf1 = glLibInternal_load_surface(path_data[3]);
			data_face_negz_surf1 = glLibInternal_load_surface(path_data[4]);
			data_face_posz_surf1 = glLibInternal_load_surface(path_data[5]);

			glLibInternal_make_set_rect_data_from(rect_data);

			#ifdef GLLIB_ERROR_MODE_REPORT_ERRORS
			//Check that the rects are reasonable
			SDL_Surface* data[6] = { data_face_negx_surf1,data_face_posx_surf1, data_face_negy_surf1,data_face_posy_surf1, data_face_negz_surf1,data_face_posz_surf1 };
			for (char i=0;i<6;++i) glLibInternal_make_check_rect( data[i], string(" loaded from file \"")+path_data[i]+"\"" );
			#endif
		}
		/*
		void* glLibInternal_make_create_duplicate_data(char face_num, Uint8*           data, int precision) const {
			switch (precision) {
				case  8: { return glLibInternal_make_duplicate_data_to_uint8(data,num_texels); }
				case 16: {} //Fall through to 24->32
				case 24: {} //Fall through to 32
				case 32: { return glLibInternal_make_duplicate_data_to_float32(data,num_texels); }
			}
			return NULL; //shouldn't happen
		}
		void* glLibInternal_make_create_duplicate_data(char face_num, float*           data, int precision) const {
			switch (precision) {
				case  8: {
					#ifdef GLLIB_ERROR_MODE_REPORT_WARNINGS
					GLLIB_ERROR_TYPE_WARNING("Requested 8-bit precision on 32-bit data!  Reducing data precision to 8-bit.");
					#endif

					return glLibInternal_make_duplicate_data_to_uint8(data,num_texels);
				}
				case 16: {} //Fall through to 24->32
				case 24: {} //Fall through to 32
				case 32: { return glLibInternal_make_duplicate_data_to_float32(data,num_texels); }
			}
			return NULL; //shouldn't happen
		}
		void* glLibInternal_make_create_duplicate_data(char face_num, double*          data, int precision) const {
			switch (precision) {
				case  8: {
					#ifdef GLLIB_ERROR_MODE_REPORT_WARNINGS
					GLLIB_ERROR_TYPE_WARNING("Requested 8-bit precision on 64-bit data!  Reducing data precision to 8-bit.");
					#endif

					return glLibInternal_make_duplicate_data_to_uint8(data,num_texels);
				}
				case 16: {} //Fall through to 24->32
				case 24: {} //Fall through to 32
				case 32: {
					//Nothing we can do about it--we'll have to reduce 64 to 32.  No warning.
					return glLibInternal_make_duplicate_data_to_float32(data,num_texels);
				}
			}
			return NULL; //shouldn't happen
		}
		void* glLibInternal_make_create_duplicate_data(char face_num, SDL_Surface*     data, int precision) const {
			switch (precision) {
				case  8: {
					data_surf2 = glLibInternal_make_desired_surface(data,x,y,width,height,texture_format);
					return glLibInternal_make_duplicate_data_to_uint8( (Uint8*)(data_surf2->pixels), num_texels );
				}
				case 16: {} //Fall through to 24->32
				case 24: {} //Fall through to 32
				case 32: {
					data_surf2 = glLibInternal_make_desired_surface(data,x,y,width,height,texture_format);
					return glLibInternal_make_duplicate_data_to_uint8( (Uint8*)(data_surf2->pixels), num_texels );
				}
			}
			return NULL; //shouldn't happen
		}
		void* glLibInternal_make_create_duplicate_data(char face_num, const char* path_data, int precision) const {
			switch (precision) {
				case  8: {
					data_surf2 = glLibInternal_make_desired_surface(data_surf1,x,y,width,height,texture_format);
					return glLibInternal_make_duplicate_data_to_uint8( (Uint8*)(data_surf2->pixels), num_texels );
				}
				case 16: {} //Fall through to 24->32
				case 24: {} //Fall through to 32
				case 32: {
					data_surf2 = glLibInternal_make_desired_surface(data_surf1,x,y,width,height,texture_format);
					return glLibInternal_make_duplicate_data_to_float32( (Uint8*)(data_surf2->pixels), num_texels );
				}
			}
			return NULL; //shouldn't happen
		}
		void* glLibInternal_make_create_duplicate_data(char face_num, int         null_data, int precision) const {
			return NULL;
		}
		*/
		template <typename type_data> void glLibInternal_make_create(char face_num, type_data data, const double colorkey[4], int precision) {
			/*switch (precision) {
				case 8:
				{
					Uint8* duplicate_data = NULL;
					if      (data1 != NULL) { //Uint8
						duplicate_data = glLibInternal_make_duplicate_data_to_uint8(data1,num_texels);
					}
					else if (data2 != NULL) { //Float32
						#ifdef GLLIB_ERROR_MODE_REPORT_WARNINGS
						GLLIB_ERROR_TYPE_WARNING("Requested 8-bit precision on 32-bit data!  Reducing data precision to 8-bit.");
						#endif
						duplicate_data = glLibInternal_make_duplicate_data_to_uint8(data2,num_texels);
					}
					else if (data3 != NULL) { //Double
						#ifdef GLLIB_ERROR_MODE_REPORT_WARNINGS
						GLLIB_ERROR_TYPE_WARNING("Requested 8-bit, precision on 64-bit data!  Reducing data precision to 8-bit.");
						#endif
						duplicate_data = glLibInternal_make_duplicate_data_to_uint8(data3,num_texels);
					}
					else if (data4 != NULL) { //SDL_Surface
						switch (face_num) {
							case 0: { data_face_negx_surf2 = glLibInternal_make_desired_surface(data4,x,y,width,height,texture_format); duplicate_data = glLibInternal_make_duplicate_data_to_uint8( (Uint8*)(data_face_negx_surf2->pixels), num_texels ); break; }
							case 1: { data_face_posx_surf2 = glLibInternal_make_desired_surface(data4,x,y,width,height,texture_format); duplicate_data = glLibInternal_make_duplicate_data_to_uint8( (Uint8*)(data_face_posx_surf2->pixels), num_texels ); break; }
							case 2: { data_face_negy_surf2 = glLibInternal_make_desired_surface(data4,x,y,width,height,texture_format); duplicate_data = glLibInternal_make_duplicate_data_to_uint8( (Uint8*)(data_face_negy_surf2->pixels), num_texels ); break; }
							case 3: { data_face_posy_surf2 = glLibInternal_make_desired_surface(data4,x,y,width,height,texture_format); duplicate_data = glLibInternal_make_duplicate_data_to_uint8( (Uint8*)(data_face_posy_surf2->pixels), num_texels ); break; }
							case 4: { data_face_negz_surf2 = glLibInternal_make_desired_surface(data4,x,y,width,height,texture_format); duplicate_data = glLibInternal_make_duplicate_data_to_uint8( (Uint8*)(data_face_negz_surf2->pixels), num_texels ); break; }
							case 5: { data_face_posz_surf2 = glLibInternal_make_desired_surface(data4,x,y,width,height,texture_format); duplicate_data = glLibInternal_make_duplicate_data_to_uint8( (Uint8*)(data_face_posz_surf2->pixels), num_texels ); break; }
						}
					}
					else if (file_path1 != NULL) { //char*
						switch (face_num) {
							case 0: { data_face_negx_surf2 = glLibInternal_make_desired_surface(data_face_negx_surf1,x,y,width,height,texture_format); duplicate_data = glLibInternal_make_duplicate_data_to_uint8( (Uint8*)(data_face_negx_surf2->pixels), num_texels ); break; }
							case 1: { data_face_posx_surf2 = glLibInternal_make_desired_surface(data_face_posx_surf1,x,y,width,height,texture_format); duplicate_data = glLibInternal_make_duplicate_data_to_uint8( (Uint8*)(data_face_posx_surf2->pixels), num_texels ); break; }
							case 2: { data_face_negy_surf2 = glLibInternal_make_desired_surface(data_face_negy_surf1,x,y,width,height,texture_format); duplicate_data = glLibInternal_make_duplicate_data_to_uint8( (Uint8*)(data_face_negy_surf2->pixels), num_texels ); break; }
							case 3: { data_face_posy_surf2 = glLibInternal_make_desired_surface(data_face_posy_surf1,x,y,width,height,texture_format); duplicate_data = glLibInternal_make_duplicate_data_to_uint8( (Uint8*)(data_face_posy_surf2->pixels), num_texels ); break; }
							case 4: { data_face_negz_surf2 = glLibInternal_make_desired_surface(data_face_negz_surf1,x,y,width,height,texture_format); duplicate_data = glLibInternal_make_duplicate_data_to_uint8( (Uint8*)(data_face_negz_surf2->pixels), num_texels ); break; }
							case 5: { data_face_posz_surf2 = glLibInternal_make_desired_surface(data_face_posz_surf1,x,y,width,height,texture_format); duplicate_data = glLibInternal_make_duplicate_data_to_uint8( (Uint8*)(data_face_posz_surf2->pixels), num_texels ); break; }
						}
					}
					if (texture_format&GLLIB_RGBA) {
						glLibInternal_evaluate_colorkey(duplicate_data,colorkey,num_texels);
					}
					data_type = GL_UNSIGNED_BYTE;
					switch (face_num) {
						case 0: data_face_negx_uint8 = duplicate_data; break;
						case 1: data_face_posx_uint8 = duplicate_data; break;
						case 2: data_face_negy_uint8 = duplicate_data; break;
						case 3: data_face_posy_uint8 = duplicate_data; break;
						case 4: data_face_negz_uint8 = duplicate_data; break;
						case 5: data_face_posz_uint8 = duplicate_data; break;
					}
					break;
				}
				case 16: //Fall through to 24->32
				case 24: //Fall through to 32
				case 32:
				{
					float* duplicate_data = NULL;
					if      (data1 != NULL) { //Uint32
						duplicate_data = glLibInternal_make_duplicate_data_to_float32(data1,num_texels);
					}
					else if (data2 != NULL) { //Float32
						duplicate_data = glLibInternal_make_duplicate_data_to_float32(data2,num_texels);
					}
					else if (data3 != NULL) { //Double
						duplicate_data = glLibInternal_make_duplicate_data_to_float32(data3,num_texels);
					}
					else if (data4 != NULL) { //SDL_Surface
						switch (face_num) {
							case 0: { data_face_negx_surf2 = glLibInternal_make_desired_surface(data4,x,y,width,height,texture_format); duplicate_data = glLibInternal_make_duplicate_data_to_float32( (Uint8*)(data_face_negx_surf2->pixels), num_texels ); break; }
							case 1: { data_face_posx_surf2 = glLibInternal_make_desired_surface(data4,x,y,width,height,texture_format); duplicate_data = glLibInternal_make_duplicate_data_to_float32( (Uint8*)(data_face_posx_surf2->pixels), num_texels ); break; }
							case 2: { data_face_negy_surf2 = glLibInternal_make_desired_surface(data4,x,y,width,height,texture_format); duplicate_data = glLibInternal_make_duplicate_data_to_float32( (Uint8*)(data_face_negy_surf2->pixels), num_texels ); break; }
							case 3: { data_face_posy_surf2 = glLibInternal_make_desired_surface(data4,x,y,width,height,texture_format); duplicate_data = glLibInternal_make_duplicate_data_to_float32( (Uint8*)(data_face_posy_surf2->pixels), num_texels ); break; }
							case 4: { data_face_negz_surf2 = glLibInternal_make_desired_surface(data4,x,y,width,height,texture_format); duplicate_data = glLibInternal_make_duplicate_data_to_float32( (Uint8*)(data_face_negz_surf2->pixels), num_texels ); break; }
							case 5: { data_face_posz_surf2 = glLibInternal_make_desired_surface(data4,x,y,width,height,texture_format); duplicate_data = glLibInternal_make_duplicate_data_to_float32( (Uint8*)(data_face_posz_surf2->pixels), num_texels ); break; }
						}
					}
					else if (file_path1 != NULL) { //char*
						switch (face_num) {
							case 0: { data_face_negx_surf2 = glLibInternal_make_desired_surface(data_face_negx_surf1,x,y,width,height,texture_format); duplicate_data = glLibInternal_make_duplicate_data_to_float32( (Uint8*)(data_face_negx_surf2->pixels), num_texels ); break; }
							case 1: { data_face_posx_surf2 = glLibInternal_make_desired_surface(data_face_posx_surf1,x,y,width,height,texture_format); duplicate_data = glLibInternal_make_duplicate_data_to_float32( (Uint8*)(data_face_posx_surf2->pixels), num_texels ); break; }
							case 2: { data_face_negy_surf2 = glLibInternal_make_desired_surface(data_face_negy_surf1,x,y,width,height,texture_format); duplicate_data = glLibInternal_make_duplicate_data_to_float32( (Uint8*)(data_face_negy_surf2->pixels), num_texels ); break; }
							case 3: { data_face_posy_surf2 = glLibInternal_make_desired_surface(data_face_posy_surf1,x,y,width,height,texture_format); duplicate_data = glLibInternal_make_duplicate_data_to_float32( (Uint8*)(data_face_posy_surf2->pixels), num_texels ); break; }
							case 4: { data_face_negz_surf2 = glLibInternal_make_desired_surface(data_face_negz_surf1,x,y,width,height,texture_format); duplicate_data = glLibInternal_make_duplicate_data_to_float32( (Uint8*)(data_face_negz_surf2->pixels), num_texels ); break; }
							case 5: { data_face_posz_surf2 = glLibInternal_make_desired_surface(data_face_posz_surf1,x,y,width,height,texture_format); duplicate_data = glLibInternal_make_duplicate_data_to_float32( (Uint8*)(data_face_posz_surf2->pixels), num_texels ); break; }
						}
					}
					if (texture_format&GLLIB_RGBA) {
						glLibInternal_evaluate_colorkey(duplicate_data,colorkey,num_texels);
					}
					data_type = GL_FLOAT;
					switch (face_num) {
						case 0: data_face_negx_float32 = duplicate_data; break;
						case 1: data_face_posx_float32 = duplicate_data; break;
						case 2: data_face_negy_float32 = duplicate_data; break;
						case 3: data_face_posy_float32 = duplicate_data; break;
						case 4: data_face_negz_float32 = duplicate_data; break;
						case 5: data_face_posz_float32 = duplicate_data; break;
					}
					break;
				}
			}
			*/
			/*void* duplicate_data = glLibInternal_make_create_duplicate_data(data, precision);

			if (texture_format&GLLIB_RGBA) {
				glLibInternal_make_create_evaluate_colorkey(duplicate_data,colorkey,num_texels);
			}

			switch (precision) {
				case  8: { data_type = GL_UNSIGNED_BYTE;   data_uint8 = (Uint8*)duplicate_data; break; }
				case 16: {} //Fall through to 24->32
				case 24: {} //Fall through to 32
				case 32: { data_type =         GL_FLOAT; data_float32 = (float*)duplicate_data; break; }
			}

			//Load data
			load_data();*/
		}

		template <typename type_data, typename type_rect, typename type_filter_min, typename type_filter_mag, typename type_colorkey> void glLibInternal_make(
			const type_data data,
			const type_rect flag_rect,
			const glLibFlagTextureFormat format,
			const type_filter_min flag_filter_min,
			const type_filter_mag flag_filter_mag,
			const type_colorkey colorkey_data,
			int precision)
		{
			//Set up various parameters and initialize pointers to NULL
			glLibInternal_make_init();

			//Set format and internal format
			glLibInternal_make_set_format(format,precision);

			//Set min and mag filter
			glLibInternal_make_set_filters(flag_filter_min,flag_filter_mag);

			for (char i=0;i<6;++i) {
				//Set colorkey
				double face_colorkey[4] = {-1.0,-1.0,-1.0,-1.0};
				glLibInternal_make_colorkey(face_colorkey, colorkey_data, format);

				//Load rect data (and, if from a file, load data)
				glLibInternal_make_rects_load_surfaces(i,data,flag_rect);

				//Process data according to precision
				glLibInternal_make_create(i, data, face_colorkey, precision);
			}
		}
};

};};