/***************************************************
 *  This program draws an American national flag.
 *  Click the right button to exit.
 **************************************************/

//multi lab version
//#include << X11/Xlib.h>
//#include << GLUT/glut.h>
//#include << OpenGL/gl.h>

//cs domain version
#include << X11/Xlib.h>
#include << GL/glut.h>
#include << GL/gl.h>

//windows version
//#include << GL/glut.h>
//#include << GL/gl.h>

#include << math.h>
#include << stdlib.h>
#include << stdio.h>

//define constants for the US flag
const double L = 0.8;  
const double A = 10.4;
const double B = 19.8;
const double C = 5.6; 
const double D = 7.6;
const double K = 0.6;//Diameter of a star
const double PI = 3.1415926;
const double leftxpos = 5.0;
const double leftypos = 5.0;
const double worldWidth = 38.0;
const double worldHeight = 20.0;        
const int screenWidth = 640;
const int screenHeight = 480;

// define a point class
class Point2   //single point w/ floating point coordinates
{
public:
    Point2() {x = y = 0.0f;} //constructor 1
    Point2(float xx, float yy) {x=xx; y=yy;} //constructor 2
    void set(float xx, float yy) {x=xx; y=yy;}
    float getX() {return x;}
    float getY() {return y;}
private:
     float x, y;
};


void myInit(void) 
{
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluOrtho2D(0.0, worldWidth, 0.0, worldHeight);//world coordinates
}

/*
	Draw a solid strip on the screen with specified
	lower left and upper right corners
*/
void drawSolidStrip(Point2 left, Point2 right)
{   
    float cx1 = left.getX(), cy1 = left.getY();
	float cx2 = right.getX(), cy2 = right.getY();
    glBegin(GL_POLYGON);
		glVertex2f(cx1, cy1);
		glVertex2f(cx2, cy1);
		glVertex2f(cx2, cy2);
		glVertex2f(cx1, cy2);
    glEnd();
}

// draws a line from point p1 to point p2
void lineTo(Point2 p1, Point2 p2) {
    glBegin(GL_LINES);
    glVertex2f((GLfloat) p1.getX(), (GLfloat) p1.getY());
	glVertex2f((GLfloat) p2.getX(), (GLfloat) p2.getY()); //draw the line
    glEnd();
}

// draw a triangle with specified vertices
void drawTriangle(Point2 p1, Point2 p2, Point2 p3)
{//draw a Triangle
    glBegin(GL_TRIANGLE_STRIP);
		glVertex2f(p1.getX(), p1.getY());
		glVertex2f(p2.getX(), p2.getY());
		glVertex2f(p3.getX(), p3.getY());
    glEnd();
}

// draw a star with lower left vertex coordinates p
void drawAStar(Point2 p)
{//draw a star with default Diameter of k
	Point2 pStar[7];
	pStar[0].set(p.getX(), p.getY());
	pStar[1].set(p.getX()+cos(PI/5.0)*K, p.getY()+K*sin(PI/5.0));
	pStar[2].set(p.getX()- K +cos(PI/5.0)*K, p.getY()+K*sin(PI/5.0));
	pStar[3].set(p.getX()+2*sin(PI/10.0)*K, p.getY());
	pStar[4].set(p.getX()+sin(PI/10.0)*K, p.getY()+cos(PI/10.0)*K);

	pStar[5].set(p.getX()+sin(PI/10.0)*K, p.getY()+cos(PI/10.0)*K/3);
	pStar[6].set(p.getX()+sin(PI/5.0)*K*2/3, p.getY()+cos(PI/5.0)*K*2/3);

	//use three triangles to draw a star
	drawTriangle(pStar[0], pStar[4], pStar[6]);
	drawTriangle(pStar[1], pStar[2], pStar[5]);
	drawTriangle(pStar[3], pStar[5], pStar[6]);
}

void myDisplay(void)
{
	glClear(GL_COLOR_BUFFER_BIT);        // clear the screen
	glViewport(0, 0, screenWidth, screenHeight);

	//draw 7 red and 6 white strips
	Point2 p1, p2;
	for(int i = 0; i < 13; i++)
	{
		if(i%2 == 0)
			glColor3f(1.0, 0.0, 0.0);//r,g,b, re-set the drawing color to red
		else
			glColor3f(1.0, 1.0, 1.0);//r,g,b, re-set the drawing color to white

		float x1 = leftxpos; 
		float y1 = leftypos + i*L;
		float x2 = x1 + B;
		float y2 = leftypos + (i+1)*L;
		p1.set(x1, y1);
		p2.set(x2, y2);
		drawSolidStrip(p1, p2);
	}

	//draw a blue square
	glColor3f(0.0, 0.0, 1.0);//r,g,b, re-set the drawing color to blue
	float x1 = leftxpos; 
	float y1 = leftypos + A - C;
	float x2 = x1 + D;
	float y2 = leftypos + A;
	p1.set(x1, y1);
	p2.set(x2, y2);
	drawSolidStrip(p1, p2);

	//draw 50 white stars
	glColor3f(1.0, 1.0, 1.0);//r,g,b// re-set the drawing color to white
	Point2 p;
	for(int i = 0; i < 6; i++) {
		for(int j=0; j<5; j++) {
			p.set(5.5 + i*7.6/6, leftypos + A - C + 0.4 + j*1.06);
			drawAStar(p);
		}
	}
	for(int i = 0; i < 5; i++) {
		for(int j=0; j<4; j++) {
			p.set(6.16 + i*7.6/6, leftypos + A - C + 0.84 + j*1.06);
			drawAStar(p);
		}
	}
	glFlush();
}

void myMouse(int button, int state, int x, int y)
{
	switch (button) {
    case GLUT_RIGHT_BUTTON:
        if (state == GLUT_DOWN)
           exit (-1);
        break;
    default:
        break;
	}
}

int main(int argc, char** argv)
{
	glutInit(&argc, argv);								// initialize the toolkit
	glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);
        // set display mode
	glutInitWindowSize (screenWidth, screenHeight);
        // set screen window size
	glutInitWindowPosition (100, 100);
        // set window position on screen
	glutCreateWindow (argv[0]);
        // open screen window
	myInit ();
	glutDisplayFunc(myDisplay);							// register redraw function
	glutMouseFunc(myMouse);								// register myMouse function
	glutMainLoop();
        // go into a perpetual loop
	return 0;
}