#include "SkyBox.h"

namespace SKYBOX
{

bool getSkyBoxTextures( const calSpace::SkyboxCAL &skybox, const TextureManager &textureManager, unsigned int dstSkyBoxTextures[6] )
{
	dstSkyBoxTextures[ SKYBOX::BOTTOM ] = textureManager.getTexture(	skybox.bottom );
	dstSkyBoxTextures[ SKYBOX::TOP ] = textureManager.getTexture(	skybox.top );
	dstSkyBoxTextures[ SKYBOX::LEFT ] = textureManager.getTexture(	skybox.left );
	dstSkyBoxTextures[ SKYBOX::RIGHT ] = textureManager.getTexture(	skybox.right );
	dstSkyBoxTextures[ SKYBOX::FRONT ] = textureManager.getTexture(	skybox.front );
	dstSkyBoxTextures[ SKYBOX::BACK ] = textureManager.getTexture(	skybox.back );

	for ( int i=0; i< 6; ++i)
	{
		if ( dstSkyBoxTextures[i] == 0 )
		{
			return false;	// texture not found in database
		}
	}

	return true;	//everythink ok
}

void CloudySkyPlane::simulate( float dt )
{
	this->centerTexCoord[0] += offsetDir[0];
	this->centerTexCoord[1] += offsetDir[1];
}
void CloudySkyPlane::render( Render &render )
{
	render.bind();
	glEnable(GL_TEXTURE_2D);
	glEnable( GL_BLEND );
	glBlendFunc( GL_ONE, GL_ONE);
	glColor4f( 1.0, 1.0, 1.0, 0.5 );

	//NOTE: texture have to be set to GL_REPEAT MODE!!!
	glBindTexture( GL_TEXTURE_2D, this->skyTexture );
	glBegin( GL_QUADS );
		glTexCoord2f( this->centerTexCoord[0]-this->texCoordSize[0], this->centerTexCoord[1]-this->texCoordSize[1]);
		glVertex3fv( skyRegion[0].getArrPtr() );

		glTexCoord2f( this->centerTexCoord[0]+this->texCoordSize[0], this->centerTexCoord[1]-this->texCoordSize[1]);
		glVertex3fv( skyRegion[1].getArrPtr() );

		glTexCoord2f( this->centerTexCoord[0]+this->texCoordSize[0], this->centerTexCoord[1]+this->texCoordSize[1]);
		glVertex3fv( skyRegion[2].getArrPtr() );

		glTexCoord2f( this->centerTexCoord[0]-this->texCoordSize[0], this->centerTexCoord[1]+this->texCoordSize[1]);
		glVertex3fv( skyRegion[3].getArrPtr() );
	glEnd();

	glDisable( GL_BLEND );
}

CloudySkyPlane::CloudySkyPlane(void)
{
	this->centerTexCoord[0] = 0.5;
	this->centerTexCoord[1] = 0.5;

	this->texCoordSize[0] = 0.1;
	this->texCoordSize[1] = 0.1;

	this->offsetDir[0] = 0.0;
	this->offsetDir[1] = 0.0;

	this->color[0] = 1.0;
	this->color[1] = 1.0;
	this->color[2] = 1.0;
	this->color[3] = 0.5;
}

StandardSkyBox::StandardSkyBox(void)
{
	this->skyboxSize= 300.0;
	
	for ( int i=0; i<6; ++i)
	{
		this->skyBoxTex.textures[i] = 0;
	}
}
void StandardSkyBox::simulate( float dt )
{
	//nothing to do ( is not dynamic skybox )
}
void StandardSkyBox::render( Render &render )
{
	render.bind();

	glPushMatrix();
	glScalef( skyboxSize, skyboxSize, skyboxSize );
	glEnable(GL_TEXTURE_2D);

	//back side
	glBindTexture( GL_TEXTURE_2D, this->skyBoxTex.textures[ FRONT ] );
	glBegin( GL_QUADS );
		glTexCoord2f( 0, 0);	glVertex3f( -1.0, -1.0, -1.0 );
		glTexCoord2f( 1, 0);	glVertex3f( 1.0, -1.0, -1.0 );
		glTexCoord2f( 1, 1);	glVertex3f( 1.0, 1.0, -1.0 );
		glTexCoord2f( 0, 1);	glVertex3f( -1.0, 1.0, -1.0 );
	glEnd();

	//front side
	glBindTexture( GL_TEXTURE_2D, this->skyBoxTex.textures[ BACK ] );
	glBegin( GL_QUADS );
		glTexCoord2f( 0, 0);	glVertex3f( 1.0, -1.0, 1.0 );
		glTexCoord2f( 1, 0);	glVertex3f( -1.0, -1.0, 1.0 );
		glTexCoord2f( 1, 1);	glVertex3f( -1.0, 1.0, 1.0 );
		glTexCoord2f( 0, 1);	glVertex3f( 1.0, 1.0, 1.0 );	
	glEnd();

	//left side
	glBindTexture( GL_TEXTURE_2D, this->skyBoxTex.textures[ LEFT ] );
	glBegin( GL_QUADS );
		glTexCoord2f( 0, 0);	glVertex3f( -1.0, -1.0, 1.0 );
		glTexCoord2f( 1, 0);	glVertex3f( -1.0, -1.0, -1.0 );
		glTexCoord2f( 1, 1);	glVertex3f( -1.0, 1.0, -1.0 );
		glTexCoord2f( 0, 1);	glVertex3f( -1.0, 1.0, 1.0 );
	glEnd();

	//right side
	glBindTexture( GL_TEXTURE_2D, this->skyBoxTex.textures[ RIGHT ] );
	glBegin( GL_QUADS );
		glTexCoord2f( 0, 0);	glVertex3f( 1.0, -1.0, -1.0 );
		glTexCoord2f( 1, 0);	glVertex3f( 1.0, -1.0, 1.0 );
		glTexCoord2f( 1, 1);	glVertex3f( 1.0, 1.0, 1.0 );
		glTexCoord2f( 0, 1);	glVertex3f( 1.0, 1.0, -1.0 );
	glEnd();

	//top side
	glBindTexture( GL_TEXTURE_2D, this->skyBoxTex.textures[ TOP ] );
	glBegin( GL_QUADS );
		glTexCoord2f( 0, 0);	glVertex3f( -1.0, 1.0, -1.0 );
		glTexCoord2f( 1, 0);	glVertex3f( 1.0, 1.0, -1.0 );
		glTexCoord2f( 1, 1);	glVertex3f( 1.0, 1.0, 1.0 );
		glTexCoord2f( 0, 1);	glVertex3f( -1.0, 1.0, 1.0 );
	glEnd();

	//bottom side
	glBindTexture( GL_TEXTURE_2D, this->skyBoxTex.textures[ BOTTOM ] );
	glBegin( GL_QUADS );
		glTexCoord2f( 0, 0);	glVertex3f( -1.0, -1.0, 1.0 );
		glTexCoord2f( 1, 0);	glVertex3f( 1.0, -1.0, 1.0 );
		glTexCoord2f( 1, 1);	glVertex3f( 1.0, -1.0, -1.0 );
		glTexCoord2f( 0, 1);	glVertex3f( -1.0, -1.0, -1.0 );
	glEnd();

	glPopMatrix();
}


StandardSkyPlane::StandardSkyPlane(void)
{
	this->size= 0.4;
	this->tex = 0;
}
void StandardSkyPlane::simulate( float dt )
{
	//nothing to do ( is not dynamic skybox )
}
void StandardSkyPlane::render( Render &render )
{
	render.bind();

	/*
	int width, height;
	glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &width);
	glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &height);
	float ratio = (float)width/(float) height;

	Billboard skyplane;
	skyplane.alpha = 1.0;
	skyplane.color.Set( 1.0, 1.0, 1.0 );
	skyplane.position = render.getCamera().pos+render.getCamera().look * -zOffset;
	skyplane.size[0] = ratio*size;
	skyplane.size[1] = size;
	skyplane.texID = this->tex;
	render.renderBillboard( skyplane );
	*/
	
	glPushMatrix();
		glLoadIdentity();

		int width, height;

		selectTextureUnit( 0 );
		glEnable( GL_TEXTURE_2D );
		glBindTexture( GL_TEXTURE_2D, this->tex );

		glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &width);
		glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &height);
	
		float ratio = (float)width/(float) height;

		//scale is dependant to the zFar
		glScalef( ratio*size * render.getProjection().zFar, size * render.getProjection().zFar, 1 );
		glEnable(GL_TEXTURE_2D);

		glColor4f( 1,1,1,1);
		glBegin( GL_QUADS );
			glTexCoord2f( 0, 0);	glVertex3f( -1.0, -1.0, render.getProjection().zFar * ( - 1.0 + EPSILON) ); //  set maximal visible zValue
			glTexCoord2f( 1, 0);	glVertex3f( 1.0, -1.0,  render.getProjection().zFar * ( - 1.0 + EPSILON) );
			glTexCoord2f( 1, 1);	glVertex3f( 1.0, 1.0,   render.getProjection().zFar * ( - 1.0 + EPSILON) );
			glTexCoord2f( 0, 1);	glVertex3f( -1.0, 1.0,  render.getProjection().zFar * ( - 1.0 + EPSILON) );
		glEnd();

	glPopMatrix();
	
}
}