
#include "SDL_opengl.h"

#include "cube.h"
#include "tweak/tweak.h"


namespace block {


namespace Cube {


static float f=0.1;
static float ff=0.3;

void front_wacky() {
	glBegin(GL_QUADS);			

	glNormal3f(0.0f,0.0f,1.0f);
	//glTexCoord2f(0,0);
	glVertex3i(1,1,1);		
	glNormal3f(f,f,1.0f);
	//glTexCoord2f(1,0);
	glVertex3i(0,1,1);		
	glNormal3f(0,f,1.0f);
	//glTexCoord2f(1,1);
	glVertex3i(0,0,1);		
	glNormal3f(f,0,1.0f);
	//glTexCoord2f(0,1);
	glVertex3i(1,0,1);		

	glEnd();
}


void back_wacky() {
	glBegin(GL_QUADS);				

	glNormal3f(0,0,-1.0f);
	//glTexCoord2f(0,0);
	glVertex3i(1,0,0);		
	glNormal3f(0,f,-1.0f);
	//glTexCoord2f(1,0);
	glVertex3i(0,0,0);		
	//glTexCoord2f(1,1);
	glNormal3f(f,0,-1.0f);
	glVertex3i(0,1,0);		
	glNormal3f(f,ff,-1.0f);
	//glTexCoord2f(0,1);
	glVertex3i(1,1,0);		

	glEnd();
}


void left_wacky() {
	glBegin(GL_QUADS);				

	glNormal3f(-1.0f,0,0);
	
	//glTexCoord2f(0,0);
	glVertex3i(0,1,1);		
	glNormal3f(-1.0f,f,0);
	//glTexCoord2f(1,0);
	glVertex3i(0,1,0);		
	glNormal3f(-1.0f,0,f);
	//glTexCoord2f(1,1);
	glVertex3i(0,0,0);		
	glNormal3f(-1.0f,f,0);
	//glTexCoord2f(0,1);
	glVertex3i(0,0,1);		

	glEnd();
}


void right_wacky() {
	glBegin(GL_QUADS);				

	glNormal3f(1.0f,0,0);
	
	//glTexCoord2f(0,0);
	glVertex3i(1,1,0);	        
	glNormal3f(1.0f,0,f);
	//glTexCoord2f(1,0);
	glVertex3i(1,1,1);		
	glNormal3f(1.0f,0,0);
	//glTexCoord2f(1,1);
	glVertex3i(1,0,1);		
	glNormal3f(1.0f,f,0);
	//glTexCoord2f(0,1);
	glVertex3i(1,0,0);		

	glEnd();
}

void top_wacky() {
	glBegin(GL_QUADS);				

	glNormal3f(0.0f,1.0f,0.0f);
	
	//glTexCoord2f(0,0);
   glVertex3i(0,1,0);
	glNormal3f(0,1.0f,f);
	//glTexCoord2f(1,0);
   glVertex3i(0,1,1);
	glNormal3f(0,1,ff);
	//glTexCoord2f(1,1);
   glVertex3i(1,1,1);
	glNormal3f(f,1,ff);
	//glTexCoord2f(0,1);
   glVertex3i(1,1,0);

	glEnd();
}
void bottom_wacky() {
	glBegin(GL_QUADS);				

	glNormal3f(0,-1,0);
	
	//glTexCoord2f(0,0);
   glVertex3i(1,0,1);
	glNormal3f(0,-1,f);
	//glTexCoord2f(1,0);
   glVertex3i(0,0,1);
	//glTexCoord2f(1,1);
	glNormal3f(f,-1,f);
   glVertex3i(0,0,0);
	//glTexCoord2f(0,1);
	glNormal3f(f,-1,0);
   glVertex3i(1,0,0);

	glEnd();
}


void front() {
	glBegin(GL_QUADS);			

	glNormal3f(0.0f,0.0f,1.0f);
	//glTexCoord2f(0,0);
	glVertex3i(1,1,1);		
	//glTexCoord2f(1,0);
	glVertex3i(0,1,1);		
	//glTexCoord2f(1,1);
	glVertex3i(0,0,1);		
	//glTexCoord2f(0,1);
	glVertex3i(1,0,1);		

	glEnd();
}


void back() {
	glBegin(GL_QUADS);				

	glNormal3f(0,0,-1.0f);
	//glTexCoord2f(0,0);
	glVertex3i(1,0,0);		
	//glTexCoord2f(1,0);
	glVertex3i(0,0,0);		
	//glTexCoord2f(1,1);
	glVertex3i(0,1,0);		
	//glTexCoord2f(0,1);
	glVertex3i(1,1,0);		

	glEnd();
}


void left() {
	glBegin(GL_QUADS);				

	glNormal3f(-1.0f,0,0);
	
	//glTexCoord2f(0,0);
	glVertex3i(0,1,1);		
	//glTexCoord2f(1,0);
	glVertex3i(0,1,0);		
	//glTexCoord2f(1,1);
	glVertex3i(0,0,0);		
	//glTexCoord2f(0,1);
	glVertex3i(0,0,1);		

	glEnd();
}


void right() {
	glBegin(GL_QUADS);				

	glNormal3f(1.0f,0,0);
	
	//glTexCoord2f(0,0);
	glVertex3i(1,1,0);	        
	//glTexCoord2f(1,0);
	glVertex3i(1,1,1);		
	//glTexCoord2f(1,1);
	glVertex3i(1,0,1);		
	//glTexCoord2f(0,1);
	glVertex3i(1,0,0);		

	glEnd();
}

void top() {
	glBegin(GL_QUADS);				

	glNormal3f(0.0f,1.0f,0.0f);
	
	//glTexCoord2f(0,0);
   glVertex3i(0,1,0);
	//glTexCoord2f(1,0);
   glVertex3i(0,1,1);
	//glTexCoord2f(1,1);
   glVertex3i(1,1,1);
	//glTexCoord2f(0,1);
   glVertex3i(1,1,0);

	glEnd();
}

void bottom() {
	glBegin(GL_QUADS);				

	glNormal3f(0,-1,0);
	
	//glTexCoord2f(0,0);
   glVertex3i(1,0,1);
	//glTexCoord2f(1,0);
   glVertex3i(0,0,1);
	//glTexCoord2f(1,1);
   glVertex3i(0,0,0);
	//glTexCoord2f(0,1);
   glVertex3i(1,0,0);

	glEnd();
}



void draw_immediate() {
	back();
	left();
	right();
	bottom();
	top();
	front();
}

typedef enum {
   MX=0,
   PX=1,
   MY=2,
   PY=3,
   MZ=4,
   PZ=5,
   DLAST=6
} direction;


static const C3f vertices[8] = {
   C3f(1.0f,1.0f,1.0f),
   C3f(1.0f,1.0f,0.0f),
   C3f(0.0f,1.0f,0.0f),
   C3f(0.0f,1.0f,1.0f),
   C3f(1.0f,0.0f,1.0f),
   C3f(1.0f,0.0f,0.0f),
   C3f(0.0f,0.0f,1.0f),
   C3f(0.0f,0.0f,0.0f)
};

static const float normals[DLAST][3]= {
	{-1,0,0},
	{1,0,0},
	{0,-1,0},
	{0,1,0},
	{0,0,-1},
	{0,0,1}
};

static const unsigned int faceindices[DLAST][4] = {
   {4,3,8,7},
   {2,1,5,6},
   {5,7,8,6},
   {2,3,4,1},
   {6,8,3,2},
   {1,4,7,5}
};

static const float texcoords[4][2]={
	{0,0},
	{1,0},
	{1,1},
	{0,1}
};


void draw_colored_immediate() {
	C3 colors[6][4];

	C3 col;

	col=Tweak::cube_back_color();
	colors[MZ][0]=col; col-=10;
	colors[MZ][1]=col; col-=10;
	colors[MZ][2]=col; col-=10;
	colors[MZ][3]=col; col-=10;

	col=Tweak::cube_front_color();
	colors[PZ][0]=col; col-=10;
	colors[PZ][1]=col; col-=10;
	colors[PZ][2]=col; col-=10;
	colors[PZ][3]=col; col-=10;

	col=Tweak::cube_left_color();
	colors[MX][0]=col; col-=10;
	colors[MX][1]=col; col-=10;
	colors[MX][2]=col; col-=10;
	colors[MX][3]=col; col-=10;

	col=Tweak::cube_right_color();
	colors[PX][0]=col; col-=10;
	colors[PX][1]=col; col-=10;
	colors[PX][2]=col; col-=10;
	colors[PX][3]=col; col-=10;

	col=Tweak::cube_top_color();
	colors[PY][0]=col; col-=10;
	colors[PY][1]=col; col-=10;
	colors[PY][2]=col; col-=10;
	colors[PY][3]=col; col-=10;

	col=Tweak::cube_bottom_color();
	colors[MY][0]=col; col-=10;
	colors[MY][1]=col; col-=10;
	colors[MY][2]=col; col-=10;
	colors[MY][3]=col; col-=10;

	C3f c;
	glBegin(GL_QUADS);
	for (unsigned int f=0;f<6;f++) {
		for (unsigned int v=0;v<4;v++) {
			c=vertices[faceindices[f][v]-1];

			if (colors[f][v].x<0) colors[f][v].x=0;
			if (colors[f][v].y<0) colors[f][v].y=0;
			if (colors[f][v].z<0) colors[f][v].z=0;
			//glTexCoord2f(texcoords[v][0],texcoords[v][1]);
			glNormal3fv(normals[f]);
			glColor3ub(colors[f][v].x,colors[f][v].y,colors[f][v].z);
			glVertex3f(c.x,c.y,c.z);

		}
	}
	glEnd();
}


static GLuint dl=0;
static GLuint dlc=0;
static GLuint dl_wacky=0;

static GLuint sides[6];
static GLuint sides_wacky[6];

void gen_dl() {
	int i;

	i=0;
   sides[i] = glGenLists(1); glNewList(sides[i],GL_COMPILE); left(); glEndList();
	i=1;
   sides[i] = glGenLists(1); glNewList(sides[i],GL_COMPILE); right(); glEndList();
	i=2;
   sides[i] = glGenLists(1); glNewList(sides[i],GL_COMPILE); bottom(); glEndList();
	i=3;
   sides[i] = glGenLists(1); glNewList(sides[i],GL_COMPILE); top(); glEndList();
	i=4;
   sides[i] = glGenLists(1); glNewList(sides[i],GL_COMPILE); back(); glEndList();
	i=5;
   sides[i] = glGenLists(1); glNewList(sides[i],GL_COMPILE); front(); glEndList();

	i=0;
   sides_wacky[i] = glGenLists(1); glNewList(sides_wacky[i],GL_COMPILE); left_wacky(); glEndList();
	i=1;
   sides_wacky[i] = glGenLists(1); glNewList(sides_wacky[i],GL_COMPILE); right_wacky(); glEndList();
	i=2;
   sides_wacky[i] = glGenLists(1); glNewList(sides_wacky[i],GL_COMPILE); bottom_wacky(); glEndList();
	i=3;
   sides_wacky[i] = glGenLists(1); glNewList(sides_wacky[i],GL_COMPILE); top_wacky(); glEndList();
	i=4;
   sides_wacky[i] = glGenLists(1); glNewList(sides_wacky[i],GL_COMPILE); back_wacky(); glEndList();
	i=5;
   sides_wacky[i] = glGenLists(1); glNewList(sides_wacky[i],GL_COMPILE); front_wacky(); glEndList();


   dl_wacky = glGenLists(1);
   glNewList(dl_wacky,GL_COMPILE);
	for (i=0;i<6;i++) {
		draw_wacky(i);
	}
	glEndList();

   dl = glGenLists(1);
   glNewList(dl,GL_COMPILE);
	for (i=0;i<6;i++) {
		draw(i);
	}
	glEndList();

   dlc = glGenLists(1);
   glNewList(dlc,GL_COMPILE);
	draw_colored_immediate();
	glEndList();
}
void draw_wacky(int side) {
	if (side==-1) {glCallList(dl_wacky); return; }
	glCallList(sides_wacky[side]);
}
void draw(int side) {
	if (side==-1) {glCallList(dl); return; }
	glCallList(sides[side]);
}
void draw_colored(int side) {
	glCallList(dlc);
}

}

} //namespace
