#include <stdio.h>
#include <stdlib.h>
#include <GL/glut.h>
#include <GL/gl.h>
#include <sys/time.h>


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 = 2;


struct screen {

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


struct screen *mainwindow=( (struct screen *) malloc(sizeof(struct screen)*5) );

double x_coord = 0;

static void Animate(void)
{
	int i;
	int x1 = 0;
	int y1 = 0;
	int z1 = 10;
	float rcalc;
	float gcalc;
	float bcalc;
	//float acalc;

	glClear(GL_COLOR_BUFFER_BIT);

	x1 = 0;
	y1 = 0;
	
	/*
	glBegin(GL_POINTS);
	glColor3f(255, 0, 0);
	glVertex3i(50, 50, 1);
        glVertex3i(51, 50, 1);
        glVertex3i(51, 51, 1);
        glVertex3i(50, 51, 1);
	glEnd();

        glBegin(GL_POINTS);
        glColor3f(255*.5, 0, 255);
        glVertex3i(50, 50, 0);
	//glColor4f(0, 0, 255, 1); 
        glVertex3i(51, 50, 0);
        glVertex3i(51, 51, 0);
        glVertex3i(50, 51, 0);
        glEnd();
	*/


	z1 = 1;
	for(i=0; i < RES*2; i+=X) {
		glBegin(GL_POINTS);
		

		
		for(x1=0; x1<X; x1++) {
			
			//if(mainwindow[x1+(y1*X)+(z1*RES)].red != 0 && mainwindow[x1+(y1*X)+(z1*RES)].green != 0 && 
                          //mainwindow[x1+(y1*X)+(z1*RES)].blue != 0) {
			if(z1 != 1) {

				rcalc = (mainwindow[x1+(y1*X)+(z1*RES)].red*mainwindow[x1+(y1*X)+(z1*RES)].alpha)+
                                        ( (mainwindow[x1+(y1*X)+((z1+1)*RES)].red )*
                                        (255-mainwindow[x1+(y1*X)+((z1)*RES)].alpha) ) ;
				rcalc = rcalc / mainwindow[x1+(y1*X)+(z1*RES)].alpha;

                                gcalc = (mainwindow[x1+(y1*X)+(z1*RES)].green*mainwindow[x1+(y1*X)+(z1*RES)].alpha)+
                                        ( (mainwindow[x1+(y1*X)+((z1+1)*RES)].green )*
                                        (255-mainwindow[x1+(y1*X)+((z1)*RES)].alpha) ) ;
                                gcalc = gcalc / mainwindow[x1+(y1*X)+(z1*RES)].alpha;

                                bcalc = (mainwindow[x1+(y1*X)+(z1*RES)].blue*mainwindow[x1+(y1*X)+(z1*RES)].alpha)+
                                        ( (mainwindow[x1+(y1*X)+((z1+1)*RES)].blue )*
                                        (255-mainwindow[x1+(y1*X)+((z1)*RES)].alpha) ) ;
                                bcalc = bcalc / mainwindow[x1+(y1*X)+(z1*RES)].alpha;




				/*
				glColor3f( (mainwindow[x1+(y1*X)+((z1+1)*RES)].red * mainwindow[x1+(y1*X)+((z1+1)*RES)].alpha)
                                            + (mainwindow[x1+(y1*X)+(z1*RES)].red * mainwindow[x1+(y1*X)+(z1*RES)].alpha),
                                            (mainwindow[x1+(y1*X)+((z1+1)*RES)].green * mainwindow[x1+(y1*X)+((z1+1)*RES)].alpha)
                                            + (mainwindow[x1+(y1*X)+(z1*RES)].green * mainwindow[x1+(y1*X)+(z1*RES)].alpha), 
                                            (mainwindow[x1+(y1*X)+((z1+1)*RES)].blue * mainwindow[x1+(y1*X)+((z1+1)*RES)].alpha)
                                            + (mainwindow[x1+(y1*X)+(z1*RES)].blue * mainwindow[x1+(y1*X)+(z1*RES)].alpha)
                                          );
				*/
				glColor3f(rcalc, gcalc, bcalc);

				//glVertex2f(x1, y1);
			}else{
				glColor3f(mainwindow[x1+(y1*X)+((z1)*RES)].red, mainwindow[x1+(y1*X)+((z1)*RES)].green, 
                                mainwindow[x1+(y1*X)+((z1)*RES)].blue);
			}
			//glLoadIdentity();
			glVertex3f(x1, y1, z1);
              		

		}

		if(y1 == Y && x1 == X && z1 > 0) {
			y1 = 0;
			z1--;
			//printf("here\n");
		}else{
			y1++;
			//z=10;
		}	


		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;

	



/*
glBegin(GL_LINES);
for(x_coord=0; x_coord<=X; x_coord+=50) {
        //glLoadIdentity();
        glColor4f( 0, 255, 0, 0);
        //glTranslatef(x_coord,0.0f,0.0f);

        //glBegin(GL_LINES);
        glVertex3f(x_coord, 0.0, 0);
        glVertex3f(x_coord, Y, 0);
        //glEnd( );
}
glEnd( );  




        glFlush();
        glutSwapBuffers();
        glutPostRedisplay();
*/


		z1 = 1;
		K = rec_center_x;
		J = rec_center_y;

		while(J < (rec_center_y + rec_length ) ) {
			while(K < (rec_center_x + rec_width ) ) {
				mainwindow[K+(X*J)+(z1*RES)].red = 0;				
				mainwindow[K+(X*J)+(z1*RES)].green = 0;
				mainwindow[K+(X*J)+(z1*RES)].blue = 0;
				mainwindow[K+(X*J)+(z1*RES)].alpha = 0;
				K++;
			}
			J++;
			K = rec_center_x;
		}


		z1 = 0;
                K = rec_center_x+uneven;
                J = rec_center_y+uneven;
                 
                while(J < (rec_center_y+uneven + rec_length ) ) {
                        while(K < (rec_center_x+uneven + rec_width ) ) {
                                mainwindow[K+(X*J)+(z1*RES)].red = 0;
                                mainwindow[K+(X*J)+(z1*RES)].green = 0;
                                mainwindow[K+(X*J)+(z1*RES)].blue = 0;
                                mainwindow[K+(X*J)+(z1*RES)].alpha = 0;
                                K++;
                        }
                        J++;
                        K = rec_center_x+uneven;
                }
                                








		if(rec_center_x < 500) {
			rec_center_x+=25;
		} else {
			rec_center_x=0;
		}

                if(rec_center_y < 500) {
                        rec_center_y+=25;
                } else {
                        rec_center_y=0;
                }  

		if(uneven == 100) {
			uneven = 50;
		}else{
			uneven = 100;
		}





		z1 = 1;
                K = rec_center_x;
                J = rec_center_y;
                while(J < (rec_center_y + rec_length) ) {
                        while(K < (rec_center_x + rec_width) ) {
                                mainwindow[K+(X*J)+(z1*RES)].red = 255;
                                mainwindow[K+(X*J)+(z1*RES)].green = 0;
                                mainwindow[K+(X*J)+(z1*RES)].blue = 0;
				mainwindow[K+(X*J)+(z1*RES)].alpha = 1;
                                K++;
                        }
                        J++;
                        K = rec_center_x;
                }


z1 = 0;
                K = rec_center_x +uneven;
                J = rec_center_y +uneven;   
                while(J < (rec_center_y+uneven + rec_length) ) {
                        while(K < (rec_center_x+uneven + rec_width) ) {
                                mainwindow[K+(X*J)+(z1*RES)].red = 0;
                                mainwindow[K+(X*J)+(z1*RES)].green = 0;
                                mainwindow[K+(X*J)+(z1*RES)].blue = 255;
                                mainwindow[K+(X*J)+(z1*RES)].alpha = 230;
                                K++;
                        }
                        J++;
                        K = rec_center_x+uneven;
                }


}





}

void OpenGLInit(void)
{
	glShadeModel( GL_FLAT );
	glClearColor( 0.0, 0.0, 0.0, 0.0 );
	glClear(GL_COLOR_BUFFER_BIT);
	glDisable( 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;

	glMatrixMode( GL_PROJECTION );
	glLoadIdentity();
	glOrtho (0, w, h, 0, 0, 1);
	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;
	

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

	if( (mainwindow = (struct screen *)realloc(mainwindow, sizeof(struct screen)*RES*DEPTH) ) ==NULL )
	{
		printf("Reallocation failed\n");
		exit(1);
	} 










	int i;
	for(i=0; i < RES*DEPTH; i++) {

                        mainwindow[i].red = 0;
                        mainwindow[i].green = 0;
                        mainwindow[i].blue = 0;
			mainwindow[i].alpha = 1;
	}


	//printf("test %d\n", mainwindow[0].alpha);


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


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



	return 0;
}
