#include <GL/glut.h>

#define SIZE 500  /* size of the graphic window */

#define M_RED 20
#define M_GREEN 21
#define M_BLUE 22

#define M_BLACK 23
#define M_YELLOW 24

GLfloat xangle, yangle, zangle; /* rotation angles */


/* draw a cube without using glutWireCube() */

void drawCube()
{
 int i, j;

 GLfloat color[][3] = {
    { 1.0, 0.0, 0.0 },  /* red     */
    { 1.0, 1.0, 0.0 },  /* yellow  */
    { 1.0, 0.0, 1.0 },  /* magenta */
    { 0.0, 0.0, 0.0 },  /* black   */
    { 0.0, 1.0, 0.0 },  /* green   */
    { 0.0, 0.0, 1.0 }   /* blue    */
 };

 GLfloat cube[][3] = {
    { -0.5, -0.5,  0.5 },
    {  0.5, -0.5,  0.5 },
    {  0.5,  0.5,  0.5 },
    { -0.5,  0.5,  0.5 },
    { -0.5, -0.5, -0.5 },
    {  0.5, -0.5, -0.5 },
    {  0.5,  0.5, -0.5 },
    { -0.5,  0.5, -0.5 }
 };

/*
 * Specify vertices in counter-clockwise order for each face
 */

 int face[][4] = {
    { 0, 1, 2, 3 },
    { 1, 5, 6, 2 },
    { 5, 4, 7, 6 },
    { 4, 0, 3, 7 },
    { 2, 6, 7, 3 },
    { 4, 5, 1, 0 }
 };

 for ( i = 0; i < 6; i++ )           /* draw all six sides */
    {
        glBegin( GL_POLYGON );
        glColor3f( color[i][0], color[i][1], color[i][2] );
        for ( j = 0; j < 4; j++ )       /* four vertices per side */
        {
            glVertex3fv( cube[face[i][j]] );
        }
        glEnd();
    }
}

/*
void display (void)
{
 glClear(GL_COLOR_BUFFER_BIT);
 glColor3f(0.0, 0.0, 0.0);
 glBegin(GL_LINES);
  glVertex2f(-1.0, 0.0);
  glVertex2f(1.0, 0.0);
 glEnd();
}
*/

void display (void)
{
 int i, j;

 glClear(GL_COLOR_BUFFER_BIT);

/* clear depth buffer as well */
/*
 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
*/

 glMatrixMode(GL_MODELVIEW);
 glLoadIdentity();
 glRotatef(xangle, 1.0, 0.0, 0.0);
 glRotatef(yangle, 0.0, 1.0, 0.0);
 glRotatef(zangle, 0.0, 0.0, 1.0);
 
/*
 drawCube();
*/

 glutWireCube(1.0);

 glutSwapBuffers();
}

void spin (void)
{
 xangle += 1.0;
 glutPostRedisplay();
}

void readkeys(unsigned char key, int x, int y)
{
  switch (key)
  {
    case 'x':
        xangle += 10.0;
        glutPostRedisplay();
        break;
    case 'y':
        yangle += 10.0;
        glutPostRedisplay();
        break;
    case 'z':
        zangle += 10.0;
        glutPostRedisplay(); 
        break;
    default:
        break;
  }
}

void mousepos(int button, int state, int x, int y)
{

  if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
  {
    xangle = x * 360.0 / SIZE;
    glutPostRedisplay();
  }
  else if (button == GLUT_MIDDLE_BUTTON && state == GLUT_DOWN)
  {
    yangle = x * 360.0 / SIZE; 
    glutPostRedisplay(); 
  } 
  else if (button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN)
  { 
    zangle = x * 360.0 / SIZE;  
    glutPostRedisplay();  
  }
} 

void drag(int x, int y)
{
 zangle= x * 360.0 / SIZE;
 xangle= y * 360.0 / SIZE;
 glutPostRedisplay();
}

void reshape (int width, int height)
{
 float aspect_ratio;
 float hvvw;       /* half width of viewing volume */
 float hvvh;       /* half height of viewing volume */

 aspect_ratio = (float) width / (float) height;

 if(width >= height) {
   hvvh = 1.0;
   hvvw = aspect_ratio;
 }
 else {
   hvvh = 1.0/aspect_ratio;
   hvvw = 1.0;
 }
 
 glViewport(0, 0, width, height);
 glMatrixMode(GL_PROJECTION);
 glLoadIdentity();
 glOrtho(-hvvw, hvvw, -hvvh, hvvh, -1, 1);
}

void choose_color(int sel)
{
 switch(sel) {
   case M_RED:
        glColor3f(1.0, 0.0, 0.0);
        break;
   case M_GREEN:
        glColor3f(0.0, 1.0, 0.0);
        break;
   case M_BLUE:
        glColor3f(0.0, 0.0, 1.0);
        break;
   default:
        break;
 }
}

void choose_red(int sel)
{
 switch(sel) {
   case M_BLACK:
        glColor3f(0.0, 0.0, 0.0);
        break;
   case M_YELLOW:
        glColor3f(1.0, 1.0, 0.0);
        break;
   default:
        break;
 }
}


void initialize_menu (void)
{
 int sub1;


 sub1 = glutCreateMenu(choose_red);
 glutAddMenuEntry("Black", M_BLACK);
 glutAddMenuEntry("Yellow", M_YELLOW);

 glutCreateMenu(choose_color);
 glutAddSubMenu("Red",sub1);
/*
 glutAddMenuEntry("Red", M_RED);
*/
 glutAddMenuEntry("Green", M_GREEN);
 glutAddMenuEntry("Blue", M_BLUE);
 glutAttachMenu(GLUT_RIGHT_BUTTON);

}

void init (void)
{
 glClearColor(1.0, 1.0, 1.0, 0.0);
 glColor3f(0.0, 0.0, 0.0);

/* Enable depth buffer */
/*
 glEnable(GL_DEPTH_TEST);
*/

/* for back-face culling */
 glEnable(GL_CULL_FACE);


 glMatrixMode(GL_PROJECTION);
 glLoadIdentity();
 glOrtho(-1, 1, -1, 1, -1, 1);
}

int main(int argc, char *argv[])
{
 glutInit(&argc,argv);

 glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);

/* for depth buffer */
/*
 glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
*/

 glutInitWindowSize(SIZE, SIZE);
 glutInitWindowPosition(100, 50);
 glutCreateWindow("My first OpenGL program");

 init();

 initialize_menu();

 glutDisplayFunc(display);
 glutIdleFunc(spin);
 glutMouseFunc(mousepos);
 glutReshapeFunc(reshape);

/*
 glutKeyboardFunc(readkeys);
 glutMotionFunc(drag);
 glutPassiveMotionFunc(drag);
*/

 glutMainLoop();
 return 0;

} 
