#include <stdio.h>
#include <stdlib.h>
#include <GL/glut.h>
#include <GL/gl.h>
#include <sys/time.h>
#include <math.h>
//include "alpha.h"
//#include "ls_shapes.h"

struct screen {

	//GLubyte red;
	//GLubyte green;
	//GLubyte blue;
	//GLubyte alpha;

        unsigned char red;
        unsigned char green;
        unsigned char blue;
        unsigned char alpha;
};

//int i, j;
struct screen ***world;


//struct screen ****world=( (struct screen ****) malloc(sizeof(struct screen ***)*101*2049*1537) );
//struct screen *mainwindow=( (struct screen *) malloc(sizeof(struct screen)*5) );
//struct screen *mainwindow2=( (struct screen *) malloc(sizeof(struct screen)*5) );

/*
struct colors {  
        unsigned char red;
        unsigned char green;
        unsigned char blue;
        unsigned char alpha;
};

struct coords {
	float x;
	float y;
	float z;
	//float w;
	//float d;
	//float h;
};
*/

struct CubePoints {
        //unsigned char red;
        //unsigned char green;
        //unsigned char blue;
        //unsigned char alpha;
        float x;
        float y;
        float z;
};

//struct CubePoints *cube=( (struct CubePoints *) malloc(sizeof(struct CubePoints)*5) );
//struct CubePoints *cube1=( (struct CubePoints *) malloc(sizeof(struct CubePoints)*100*100*5) );
//struct CubePoints *cube2=( (struct CubePoints *) malloc(sizeof(struct CubePoints)*100*100*5) );


//class Cube {
//};
//CubeColors[1]
//CubeCoords[1]


void OpenGLInit(void);
static void Animate(void );
static void ResizeWindow(int w, int h);
struct timespec ts;
struct timeval starttime,endtime;

double fps = 0;
double time1 = 0;
double time2 = 0;

int rec_center_x = 0;
int rec_center_y = 0;
int rec_width = 100;
int rec_length = 100;
int rec_rotation = 0;
int uneven = 50;
int K, J;
int X;
int Y;  
int RES;
int DEPTH = 3;
float rgbcalcs[8]= { 0 } ;
//float rgbcalcs[8];
#include "alpha.h"
#include "ls_shapes.h"


double x_coord = 0;

static void Animate(void)
{
	/*
	int iscreated;

	if(iscreated != 1) {
		struct CubePoints *cube1=( (struct CubePoints *) malloc(sizeof(struct CubePoints)*100*100*5) );
		struct CubePoints *cube2=( (struct CubePoints *) malloc(sizeof(struct CubePoints)*100*100*5) );
		iscreated = 1;
	}
	*/

	glClear(GL_COLOR_BUFFER_BIT);
	glLoadIdentity();

	register long unsigned int i;
	register long unsigned int counter1, counter2, counter3;

	//drawl_world(10);

	/*
	glBegin(GL_POINTS);
	glColor4f( 255, 0 , 0, 255);
	glVertex3f(500, 501, 1);
	glVertex3f(501, 500, 1);
	glVertex3f(501, 501, 1);
	glVertex3f(500, 500, 1);
	glVertex3f(502, 500, 1);
	glEnd();
	*/

	
	glBegin(GL_POINTS);
        for(counter1=25; counter1 > 0; counter1--) {
                for(counter2=0; counter2 < X; counter2++) {
                        for(counter3=0; counter3 < Y; counter3++) {
                                alpha( counter1, counter2, counter3 );
				//glLoadIdentity();
                                glColor3f( rgbcalcs[0], rgbcalcs[1], rgbcalcs[2]);
                                glVertex3f(counter2, counter3, counter1);
			}
		}
	}
	glEnd();
	

	glFlush();
	glutSwapBuffers();
	glutPostRedisplay();

	time2++;

	gettimeofday(&endtime, NULL);
	time1=((double)(endtime.tv_sec*1000000-starttime.tv_sec*1000000+endtime.tv_usec-starttime.tv_usec))/1000000;

        if (time2 == 5)
        {
                fps = time2 / time1;
                printf("fps: %lf - %lf frames in %lf seconds\n", fps, time2, time1);
                gettimeofday(&starttime, NULL);
                time2 = 0;

	}





}


void OpenGLInit(void)           
{       
        glShadeModel( GL_FLAT );
        glClearColor( 0.0, 0.0, 0.0, 0.0 );
        glClear(GL_COLOR_BUFFER_BIT);
        glDisable( GL_DEPTH_TEST );
	//glClearDepth(100.0f);							// Depth Buffer Setup
	//glEnable(GL_DEPTH_BUFFER_BIT);
	//glEnable(GL_DEPTH_TEST);						// Enables Depth Testing
	//glEnable(GL_DEPTH_TEST);
	//glDepthMask(GL_TRUE);
	//glEnable(GL_TEXTURE_3D);

	//glDepthFunc(GL_LEQUAL);							// The Type Of Depth Test To Do

}
        
        
static void ResizeWindow(int w, int h)  
{
        float aspectRatio;
        h = (h == 0) ? 1 : h;
        w = (w == 0) ? 1 : w;
        glViewport( 0, 0, w, h );       // View port uses whole window
        aspectRatio = (float)w/(float)h;

        glMatrixMode( GL_PROJECTION );
        glLoadIdentity();
	//glOrtho(0,w,0,h,-100,100);
        glOrtho (0, w, h, 0, -1, 100);
        glMatrixMode( GL_MODELVIEW );
	
}       



/*
void OpenGLInit(void)
{
    glShadeModel( GL_FLAT ); 
    glClearColor( 0.0, 0.0, 0.0, 0.0 );
    glClearDepth( 1.0 );
    glEnable( GL_DEPTH_TEST );
}       
        
static void ResizeWindow(int w, int h)
{
    float aspectRatio;
        h = (h == 0) ? 1 : h;
        w = (w == 0) ? 1 : w;
        glViewport( 0, 0, w, h );       // View port uses whole window
        aspectRatio = (float)w/(float)h;
  
        // Set up the projection view matrix (not very well!)
    glMatrixMode( GL_PROJECTION );
    glLoadIdentity();

    gluPerspective( 45.0, aspectRatio, 0.0, 100.0 );
      //  glLoadIdentity();
        //glOrtho (0, w, h, 0, 0, 1);
        // Select the Modelview matrix
    glMatrixMode( GL_MODELVIEW );
}
*/




int main(int argc, char** argv) {

        glutInit(&argc,argv);
        glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB );
        glutInitWindowPosition( 0, 0 );

	Y = glutGet(GLUT_SCREEN_HEIGHT); 
	X = glutGet(GLUT_SCREEN_WIDTH);
	RES = X*Y;
	register long unsigned int i, counter1, counter2 ,counter3;

	printf("res: %d x: %d y: %d\n", RES, X, Y);

	//struct screen ***world=( (struct screen ***) malloc(sizeof(struct screen **)*10) );
	//array[0] = (int *)malloc(nrows * ncolumns * sizeof(int));

/*	if( (world[100] = ( struct screen **)realloc(world[100], sizeof(struct screen *)*X*Y) ) ==NULL )
	{
		printf("Reallocation failed\n");
		exit(1);
	} 
*/

	int j;


    //struct screen ***world;

    world= (struct screen ***)malloc(100*sizeof(struct screen *) );
    for( i=0; i<100 ; i++ )
    {
        world[ i ] = ( struct screen **)malloc(X* sizeof(struct screen **) );
        for( j=0; j<X; j++)
        {
            world[ i ][ j ] = ( struct screen *)malloc(Y* sizeof(struct screen ***) );
        }
    }



printf("world initialized! size: %lu \n", sizeof(world));
//exit(0);


        for(counter1=0; counter1 < 100; counter1++) {
                for(counter2=0; counter2 < X; counter2++) {
                        for(counter3=0; counter3 < Y; counter3++) {
				//printf("z: %lu x: %lu y %lu\n", counter1, counter2, counter3);
                                world[counter1][counter2][counter3].red = 0;
                                world[counter1][counter2][counter3].green = 0;
                                world[counter1][counter2][counter3].blue = 0;
                                world[counter1][counter2][counter3].alpha = 0;
                        }
                }
        }



//world[3][2][1].green = 255;

/*
        for(counter1=0; counter1 < 10; counter1++) {
                for(counter2=0; counter2 < 5; counter2++) {
                        for(counter3=0; counter3 < 5; counter3++) {
                                printf("z: %lu x: %lu y %lu ", counter1, counter2, counter3);
				printf("%d\n", world[counter1][counter2][counter3].green);
                                //world[counter1][counter2][counter3].red = 0;
                                //world[counter1][counter2][counter3].green = 1;
                                //world[counter1][counter2][counter3].blue = 0;
                                //world[counter1][counter2][counter3].alpha = 0;
                        }
                }
        }   

*/



	
//exit(0);

	
	
	/*
	for(i=0; i < RES*100; i++) {

                        world[i].red = 0;
                        world[i].green = 0;
                        world[i].blue = 0;
			world[i].alpha = 0;

                        //mainwindow2[i].red = 0;  
                        //mainwindow2[i].green = 0;
                       // mainwindow2[i].blue = 0; 
                       // mainwindow2[i].alpha = 0;

	}
	*/

	printf("world populated!\n");

	rgbcalcs[0] = 0;
	rgbcalcs[1] = 0;
	rgbcalcs[2] = 255;
	rgbcalcs[3] = 65;
	ls_cube_to_array(500, 500, 4, 100, 100, 8);

        rgbcalcs[0] = 255;
        rgbcalcs[1] = 0;
        rgbcalcs[2] = 0;
        rgbcalcs[3] = 65;
	ls_cube_to_array(450, 450, 5, 100, 100, 8);

	printf("res*depth %d\n", RES*DEPTH);

	//mainwindow[9437183].red = 255;
	//mainwindow[9437183].green = 255;
	//printf("red: %d\n", mainwindow[9437183].red);

	//9437184

	glutInitWindowSize( X, Y );
	glutCreateWindow( "lsrender test" );


	OpenGLInit();
	glutReshapeFunc( ResizeWindow );
	glutDisplayFunc( Animate );
	glutMainLoop(  );



	return 0;
}
