#include "../include/zf.h"

#define COLOUR_INCREMENT 0.0001f

static float size;

static char top_filename[80];
static char bottom_filename[80];
static char front_filename[80];
static char back_filename[80];
static char left_filename[80];
static char right_filename[80];

static CLtexture* top;
static CLtexture* bottom;
static CLtexture* front;
static CLtexture* back;
static CLtexture* left;
static CLtexture* right;

static CLcolour colour;
static int sky_mode;  /* 0 - go to red, 1 - go to black */

static void
load_texture(CLtexture** texture, const char* filename)
{
    if (!(*texture = clioLoadTexture(filename)))
    {
	printf("could not load texture for sky: %s\n", filename);
    }

    (*texture)->wrap_s = GL_CLAMP_TO_EDGE;
    (*texture)->wrap_t = GL_CLAMP_TO_EDGE;
    (*texture)->min_filter = GL_LINEAR;
    (*texture)->mag_filter = GL_LINEAR;
    
    clUpdateTexture(*texture);
}

static void
init(void)
{
    size = 2500.0f;  /* TODO - skybox size should depend on heightmap size */

    top = 0;
    bottom = 0;
    front = 0;
    back = 0;
    left = 0;
    right = 0;

    cluSetColour(&colour,1.0f,1.0f,1.0f,1.0f);
    sky_mode = 0;
}

static void
read_textures(void)
{
    load_texture(&top, top_filename);
    load_texture(&bottom, bottom_filename);
    load_texture(&front, front_filename);
    load_texture(&back, back_filename);
    load_texture(&left, left_filename);
    load_texture(&right, right_filename);
}

static void
read(FILE* stream)
{
    fscanf(stream, "ZfSkyBox\n{\n");
    
    fscanf(stream, "top_filename = %s\n", top_filename);
    fscanf(stream, "bottom_filename = %s\n", bottom_filename);
    fscanf(stream, "front_filename = %s\n", front_filename);
    fscanf(stream, "back_filename = %s\n", back_filename);
    fscanf(stream, "left_filename = %s\n", left_filename);
    fscanf(stream, "right_filename = %s\n", right_filename);
 
    fscanf(stream, "}\n");

    read_textures();
}

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

void
zf_skybox_render(void)
{
    double viewport[4];
    
    glGetDoublev(GL_VIEWPORT, viewport);

    glPushAttrib(GL_ALL_ATTRIB_BITS); /* GL_LIGHTING_BIT | GL_CURRENT_BIT | GL_ENABLE_BIT); */

    glMatrixMode(GL_PROJECTION);
    glPushMatrix();
    glLoadIdentity();
    /* haX0r! sizes should... stored...? calculated meaningfully? */
    gluPerspective(60.0, /* should this be given/calculated? */
		   (double)viewport[2]/(double)viewport[3],
		   (double)size/2.0, (double)size * 4.0);

    glMatrixMode(GL_MODELVIEW);
    
    glColor3f(colour.r,
	      colour.g,
	      colour.b);
    switch(sky_mode)
    {
    case 0:
	colour.g -= COLOUR_INCREMENT / 2.0f;
	colour.b -= COLOUR_INCREMENT;
	if(colour.b < 0.1f)
	    sky_mode = 1;
	break;
    case 1:
	colour.g -= COLOUR_INCREMENT;
	if(colour.g < 0.2f)
	    sky_mode = 2;
	break;
    case 2:
	colour.r -= COLOUR_INCREMENT;
	if(colour.r < 0.1f)
	    sky_mode = 3;
	break;
    case 3:
	colour.r += COLOUR_INCREMENT;
	if(colour.r > 0.5f)
	    sky_mode = 4;
	break;
    case 4:
	colour.g += COLOUR_INCREMENT;
	colour.b += COLOUR_INCREMENT;
	if(colour.g > 0.95f)
	    sky_mode = 0;
	break;
    default:
	/*do nothing*/
	break;
    }

    glDisable(GL_DEPTH_TEST);
    glEnable(GL_TEXTURE_2D);
    glDisable(GL_LIGHTING);

    /* what a mess, whack this stuff in a display list or
       something... seriously! */
    clLoadTexture(top);

    glBegin(GL_QUADS);
    glTexCoord2f(0.0f, 1.0f); 
    glVertex3f(-size, size, -size);
    glTexCoord2f(1.0f, 1.0f);
    glVertex3f(size, size, -size);
    glTexCoord2f(1.0f, 0.0f);
    glVertex3f(size, size, size);
    glTexCoord2f(0.0f, 0.0f);
    glVertex3f(-size, size, size);
    glEnd();

    clLoadTexture(bottom);
  
    glBegin(GL_QUADS);        
    glTexCoord2f(0.0f, 1.0f); 
    glVertex3f(-size, -size, size);
    glTexCoord2f(1.0f, 1.0f);
    glVertex3f(size, -size, size);
    glTexCoord2f(1.0f, 0.0f);
    glVertex3f(size, -size, -size);
    glTexCoord2f(0.0f, 0.0f);
    glVertex3f(-size, -size, -size);
    glEnd();

    clLoadTexture(front);
  
    glBegin(GL_QUADS);        
    glTexCoord2f(0.0f, 1.0f); 
    glVertex3f(-size, -size, -size);
    glTexCoord2f(1.0f, 1.0f);
    glVertex3f(size, -size, -size);
    glTexCoord2f(1.0f, 0.0f);
    glVertex3f(size, size, -size);
    glTexCoord2f(0.0f, 0.0f);
    glVertex3f(-size, size, -size);
    glEnd();

    clLoadTexture(back);

    glBegin(GL_QUADS);        
    glTexCoord2f(0.0f, 1.0f); 
    glVertex3f(size, -size, size);
    glTexCoord2f(1.0f, 1.0f);
    glVertex3f(-size, -size, size);
    glTexCoord2f(1.0f, 0.0f);
    glVertex3f(-size, size, size);
    glTexCoord2f(0.0f, 0.0f);
    glVertex3f(size, size, size);
    glEnd();

    clLoadTexture(left);
  
    glBegin(GL_QUADS);        
    glTexCoord2f(0.0f, 1.0f); 
    glVertex3f(size, -size, -size);
    glTexCoord2f(1.0f, 1.0f);
    glVertex3f(size, -size, size);
    glTexCoord2f(1.0f, 0.0f);
    glVertex3f(size, size, size);
    glTexCoord2f(0.0f, 0.0f);
    glVertex3f(size, size, -size);
    glEnd();

    clLoadTexture(right);
  
    glBegin(GL_QUADS);        
    glTexCoord2f(0.0f, 1.0f); 
    glVertex3f(-size, -size, size);
    glTexCoord2f(1.0f, 1.0f);
    glVertex3f(-size, -size, -size);
    glTexCoord2f(1.0f, 0.0f);
    glVertex3f(-size, size, -size);
    glTexCoord2f(0.0f, 0.0f);
    glVertex3f(-size, size, size);
    glEnd();

    glMatrixMode(GL_PROJECTION);
    glPopMatrix();

    glMatrixMode(GL_MODELVIEW);

    glPopAttrib();
}

/* ZF_NEW STUFF!!!! */

void
zf_skybox_init(char* filename)
{
    init();
    
    /* haxor! */
    {
	FILE* stream;
	
	stream = fopen(filename, "r");

	/* check fopen */
	if (!stream)
	{
	    printf("%s() : ERROR : load skybox file %s\n", __FUNCTION__, filename);
	    exit(1);
	}
		

	read(stream);

	fclose(stream);
    }
}
