/** SGX

The   sss    gggg x   x   
     s      g      x x    Engine
      sss   g  gg   x
         s  g   g  x x          Copyright 1995-2008.
     ssss    gggg x   x         Steven Goodwin. All Rights Reserved.
    
This version has been released under the GNU Public License v2.0.

Please see the license files for details.

File: src/drivers/common/opengl/oglprimitives.cpp

*/

#include "sgx/core/core.hpp"
#include "sgx/graphics/graphics.hpp"
#include "drivers/common/opengl/opengl.hpp"

namespace {
	tREAL32 CuboidUVList[] = {
	0,0,  1.0f,0,   1.0f,1.0f,   0,1.0f,
	0,0,  1.0f,0,   1.0f,1.0f,   0,1.0f,
	0,0,  1.0f,0,   1.0f,1.0f,   0,1.0f,
	0,0,  1.0f,0,   1.0f,1.0f,   0,1.0f,
	0,0,  1.0f,0,   1.0f,1.0f,   0,1.0f,
	0,0,  1.0f,0,   1.0f,1.0f,   0,1.0f,
};

};

void 
COpenGLEngine::drawPrimitiveCuboidImpl(const sgxGfxCuboid &cuboid, const sgxMatrix43 &transform)
{
sgxVector3 CuboidVertexList[] = {
    sgxVector3( cuboid.m_vMinpos.x, cuboid.m_vMaxpos.y, cuboid.m_vMinpos.z), 
    sgxVector3( cuboid.m_vMaxpos.x, cuboid.m_vMaxpos.y, cuboid.m_vMinpos.z), 
    sgxVector3( cuboid.m_vMaxpos.x, cuboid.m_vMaxpos.y, cuboid.m_vMaxpos.z), 
    sgxVector3( cuboid.m_vMinpos.x, cuboid.m_vMaxpos.y, cuboid.m_vMaxpos.z), 
    sgxVector3( cuboid.m_vMinpos.x, cuboid.m_vMinpos.y, cuboid.m_vMinpos.z), 
    sgxVector3( cuboid.m_vMaxpos.x, cuboid.m_vMinpos.y, cuboid.m_vMinpos.z), 
    sgxVector3( cuboid.m_vMaxpos.x, cuboid.m_vMinpos.y, cuboid.m_vMaxpos.z), 
    sgxVector3( cuboid.m_vMinpos.x, cuboid.m_vMinpos.y, cuboid.m_vMaxpos.z), 
};

static tUINT32 FaceList[] = {
	 0, 1, 2, 3,	 // top 
    7, 6, 5, 4,    // bottom
    1, 0, 4, 5,    // back
    3, 2, 6, 7,    // front
    0, 3, 7, 4,    // left
    2, 1, 5, 6,    // right
};

	GLenum mode = getOGLMode();
	sgxColorRGBA &col = m_PrimitiveColor.getState();

	oglMatrix mtx(transform);

	CSGXGraphicsEngine::drawPrimitiveCuboidImpl(cuboid, transform);

    glEnableClientState(GL_VERTEX_ARRAY);
    glVertexPointer(3, GL_FLOAT, 0, (void *)CuboidVertexList);

	const sgxCuboidFace *pFace = &cuboid.face[0];
    for(int i=0;i<24;i+=4,++pFace)  {
		
		pFace->pTexture->set();

		glBegin(mode);
/*
			// TODO: pTexture param to TM
			tREAL32 u = cuboid.face[i].uv.u1;
			tREAL32 v = cuboid.face[i].uv.u1;

			sgxVector2 uv(u, v);
			CSGXTextureManager::get()->evaluateUV(uv);
			glTexCoord2f(uv.x, uv.y);

  // TODO: Pre-compute colors too
*/
			glTexCoord2f(CuboidUVList[i*2+0], CuboidUVList[i*2+1]); 
			glColor4f(pFace->color[0].r*col.r, pFace->color[0].g*col.g, pFace->color[0].b*col.b, pFace->color[0].a*col.a);
			glArrayElement( FaceList[i+0]);
		    
			glTexCoord2f(CuboidUVList[i*2+2], CuboidUVList[i*2+3]); 
			glColor4f(pFace->color[1].r*col.r, pFace->color[1].g*col.g, pFace->color[1].b*col.b, pFace->color[1].a*col.a);
		    glArrayElement( FaceList[i+1]);
		    
			glTexCoord2f(CuboidUVList[i*2+4], CuboidUVList[i*2+5]); 
			glColor4f(pFace->color[2].r*col.r, pFace->color[2].g*col.g, pFace->color[2].b*col.b, pFace->color[2].a*col.a);
		    glArrayElement( FaceList[i+2]);

			glTexCoord2f(CuboidUVList[i*2+6], CuboidUVList[i*2+7]); 
			glColor4f(pFace->color[3].r*col.r, pFace->color[3].g*col.g, pFace->color[3].b*col.b, pFace->color[3].a*col.a);
		    glArrayElement( FaceList[i+3]);
	    glEnd();
	}
    
	glDisableClientState(GL_VERTEX_ARRAY);
}


void COpenGLEngine::drawPrimitiveCuboid(const CSGXTexture **pTextures, const sgxMatrix43 &transform, const sgxVector3 &m_vMinpos, const sgxVector3 &m_vMaxpos)
{
sgxGfxCuboid cuboid;
cuboid.m_vMinpos = m_vMinpos;
cuboid.m_vMaxpos = m_vMaxpos;

for(int f=0;f<6;++f) {
	cuboid.face[f].pTexture = pTextures[f];
	cuboid.face[f].color[0] = sgxColorRGBA::White;
	cuboid.face[f].color[1] = sgxColorRGBA::White;
	cuboid.face[f].color[2] = sgxColorRGBA::White;
	cuboid.face[f].color[3] = sgxColorRGBA::White;
// TODO: Move into helper function
	// TODO: add to ctor
	cuboid.face[f].uv.u1 = CuboidUVList[f*8 + 0];
	cuboid.face[f].uv.v1 = CuboidUVList[f*8 + 1];
	cuboid.face[f].uv.u2 = CuboidUVList[f*8 + 4];
	cuboid.face[f].uv.v2 = CuboidUVList[f*8 + 5];
}

	CSGXGraphicsEngine::drawPrimitiveCuboid(cuboid, transform);
// TODO: add isAlphaSortable to sgxPrimitive... types

}

void
COpenGLEngine::drawPrimitiveSphereImpl(const sgxGfxSphere &sphere, const sgxMatrix43 &transform)
{
	CSGXGraphicsEngine::drawPrimitiveSphereImpl(sphere, transform);

	sgxColorRGBA &col = m_PrimitiveColor.getState();

	oglMatrix mtx(transform);

	glColor4f(col.r, col.g, col.b, col.a);

	CSGXTexture *txt = CSGXTextureManager::get()->getCurrentTexture();
	CSGXOpenGLSurface *pSurf = static_cast<CSGXOpenGLSurface *>(txt->m_pSurface);

	if (pSurf->m_pProperty && pSurf->m_pProperty->drawSphere(sphere.m_fRadius)) {
		// No nothing, as the property handler has taken care of it all
	} else if (m_PrimitiveMode.getState() == eWireframe) {
		glutWireSphere(sphere.m_fRadius, 16, 16);
	} else {
		glutSolidSphere(sphere.m_fRadius, 16, 16);
	}
}

void COpenGLEngine::drawLine3D(const sgxVector3 &from, const sgxVector3 &to)
{
	CSGXGraphicsEngine::drawLine3D(from, to);

	oglMatrix m;

	sgxColorRGBA &col = m_PrimitiveColor.getState();

	glColor3f(col.r, col.g, col.b);
	glBegin(GL_LINES);
		glVertex3f(from.x, from.y, from.z);
		glVertex3f(to.x, to.y, to.z);
	glEnd();
}

void 
COpenGLEngine::drawTriStrip(const CSGXTexture	*pTexture, const sgxVector<sgxPolyVtx> &vtx)
{
	CSGXGraphicsEngine::drawTriStrip(pTexture, vtx);

	CSGXTextureManager::get()->applyTexture(pTexture);
// TODO: ALPHA SORT THIS
// TODO: FIx UV's, apply color
	glBegin(GL_TRIANGLE_STRIP);
		sgxVector<sgxPolyVtx>::const_iterator cit = vtx.begin();
		for(;cit!=vtx.end();++cit) {
			glTexCoord2f((*cit).u, (*cit).v);
			glVertex3f((*cit).vect.x, (*cit).vect.y, (*cit).vect.z);
		}
	glEnd();

}

void 
COpenGLEngine::drawQuadStrip(const CSGXTexture *pTexture, const sgxVector<sgxPolyVtx> &vtx)
{
	CSGXGraphicsEngine::drawQuadStrip(pTexture, vtx);

	sgxAssert((vtx.size() % 4) == 0);
// TODO: ALPHA SORT THIS
// TODO: FIx UV's, apply color
	
	CSGXTextureManager::get()->applyTexture(pTexture);

	glBegin(GL_QUAD_STRIP);
		sgxVector<sgxPolyVtx>::const_iterator cit = vtx.begin();
		for(;cit!=vtx.end();++cit) {
			glTexCoord2f((*cit).u, (*cit).v);
			glVertex3f((*cit).vect.x, (*cit).vect.y, (*cit).vect.z);
		}
	glEnd();

}

