
#define GL_GLEXT_PROTOTYPES

#include <GL/glext.h>

#include <GL/gl.h> // GL 1.1 functions 

#include <GL/glx.h>

#include "./texture2D.h"

#include "stdbool.h"

#include "../array.h"

#include "../vector3.h"

class sampler2D{

	texture2D *		texture;

	array * textures	= new array();


	GLuint 			glTexture;
	

	GLint			binded			= false;
	

	GLint			filter 			= GL_LINEAR;
		

	GLint			MIN_FILTER 		= GL_LINEAR;

	GLint			MAG_FILTER 		= GL_LINEAR;
		
	GLint			WRAP_S 			= GL_REPEAT;

	GLint			WRAP_T 			= GL_REPEAT;
		

	GLint			datatype 		= GL_RGBA;

	GLint			format 			= GL_RGBA;

	GLint			internalFormat 	= GL_RGBA;
		

	GLint			target			= GL_TEXTURE_2D;
		
	GLint			type 			= GL_UNSIGNED_BYTE;//gl.FLOAT;


	vector3	* 		cubeSize		= NULL;


	GLint 			border			= false;

	GLint			generateMipmap	= true;

	bool			UNPACK_ALIGNMENT 	= false;

	//GLint	FLIP_Y = true; pixelStorei

	GLuint index	= 0;

	constructor() {

		glGenTextures( 1, &this->glTexture );

	}

	addTexture( texture2D *	texture ) {

		this->textures->add( texture );

	}

	int getTextureIndex() {

		int numberOfTextures	=  this->textures->length();

		return numberOfTextures;

	}

	bind() {

		this->binded = true;
/*
		texture2D *	texture	= this->texture;

		if( texture == NULL ) {

			printf("Error:		Texture not loaded.\n\n");

			return ;

		}
*/
		//printf("Created sampler with id #%i\n", this->index);

		glActiveTexture( GL_TEXTURE0 + this->index );

		glBindTexture( this->target, this->glTexture );

		glTexParameteri( this->target, GL_TEXTURE_WRAP_S, this->WRAP_S );

		glTexParameteri( this->target, GL_TEXTURE_WRAP_T, this->WRAP_T );

		glTexParameteri( this->target, GL_TEXTURE_MIN_FILTER, this->MIN_FILTER );

		glTexParameteri( this->target, GL_TEXTURE_MAG_FILTER, this->MAG_FILTER );



		if( this->target == GL_TEXTURE_2D_ARRAY ) {

			//printf("create 2d array texture");

			int offsetX 			= 0;

			int offsetY 			= 0;

			int offsetZ 			= 0;

			int depth 				= 1;

			int levelOfDetail		= 0;

			int layerCount 			= 2;

			int mipLevelCount		= 1;

			int currentLayer		= 0;

			texture2D * texture1 = this->textures->get( 0 );

			int numberOfTextures	=  this->textures->length();

			
			if( this->cubeSize == NULL ) {

				this->cubeSize	= new vector3( texture1->width, texture1->height, numberOfTextures );

			}

			//glTexSubImage3D( this->target, levelOfDetail, offsetX, offsetY, offsetZ, texture->width, texture->height, depth, this->format, this->type, texture->data );
			
			if( this->UNPACK_ALIGNMENT ) {

				glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );

			} else {

				glPixelStorei( GL_UNPACK_ALIGNMENT, 0 );

			}

			glTexStorage3D( this->target, mipLevelCount, this->format, this->cubeSize->x, this->cubeSize->y, numberOfTextures );

			GLint data[ texture1->width * texture1->height * numberOfTextures ];

			glTexImage3D( GL_TEXTURE_2D_ARRAY, levelOfDetail, this->internalFormat, this->cubeSize->x, this->cubeSize->y, numberOfTextures, this->border, this->format, this->type, data);

			for (int i = 0; i < numberOfTextures; ++i)
			{

				texture2D * currentTexture = this->textures->get( i );

				float test =  0;//this->cubeSize->y - currentTexture->height - 1;

				glTexSubImage3D( 	this->target, 
									0, 
									offsetX, test , i, 
									currentTexture->width, currentTexture->height, 1, 
									this->format, 
									this->type, 
									currentTexture->data );

			}



		} else {

			texture2D * texture = this->textures->get( 0 );

			glTexImage2D( this->target, 0, this->internalFormat, texture->width, texture->height, this->border, this->format, this->type, texture->data ); //GL_FLOAT

		}


		if( this->generateMipmap ) {

			glGenerateMipmap( this->target );

		}
		

		//glBindTexture( this->target, NULL );

	}



}
