#include <stdlib.h>
#include <stdio.h>
#include "GL/glut.h"

/* global definitions */

#define WIN_SIZE_X 400
#define WIN_SIZE_Y 400

#define MODE_1 1
#define MODE_2 2
#define MODE_3 3

int win_width;
int win_height;

int mouse_x = WIN_SIZE_X / 2;
int mouse_y = WIN_SIZE_Y / 2;

void keyboard (unsigned char key, int x, int y) {
  if (key == 27)		/* ascii-code for escape */
    exit (0);
  else
    printf ("key: %c\n", key);
}


void mouseButton (int button, int state, int x, int y) {
  if (state == GLUT_DOWN)
    {
      if (button == GLUT_LEFT_BUTTON)
	printf ("you pressed the left mousebutton at (%i/%i)\n", x, y);
    }
  else
    printf ("you released a mousebutton\n");

}

void mouseMotion (int x, int y) {
  printf ("current position: (%i/%i)\n", x, y);
  mouse_x = x;
  mouse_y = y;
  glutPostRedisplay ();
}

void menu (int state) {
  switch (state)
    {
    case MODE_1:
      printf ("you chose mode 1\n");
      break;
    case MODE_2:
      printf ("you chose mode 2\n");
      break;
    case MODE_3:
      printf ("you chose mode 3\n");
      break;
    default:			/* define your default action */ ;
    }
}

void drawQuad() {
  glBegin(GL_QUADS);
    glVertex3f(0.0, 0.0, 0.0);
    glVertex3f(1.0, 0.0, 0.0);
    glVertex3f(1.0, 1.0, 0.0);
    glVertex3f(0.0, 1.0, 0.0);
  glEnd();
}

void drawCube() {
  GLUquadricObj *cube = gluNewQuadric();
  glShadeModel(GL_FLAT);
  glPushMatrix();
    glTranslated(0.0, 0.0, -0.5);
    gluCylinder(cube, 0.5, 0.5, 1.0, 4, 1);
	gluDisk(cube, 0.0, 0.5, 4, 1);
	glTranslated(0.0, 0.0, 1.0);
	gluDisk(cube, 0.0, 0.5, 4, 1);
  glPopMatrix();
  gluDeleteQuadric(cube);
}

void drawSocket () {
	GLUquadricObj *socket = gluNewQuadric ();

	glPushMatrix ();
	glColor3f (0.0, 0.0, 1.0);
	glRotatef (20.0, 0.0, 0.0, 1.0);
  glTranslatef (250.0, 50.0, 0.0);
	gluCylinder (socket, 40.0, 40.0, 40.0, 4, 1);

	glPopMatrix ();
	gluDeleteQuadric (socket);
}
void drawMyObjects () {
  /* Viewing transformation - using identity matrix */

  /* Model transformations */
  glEnable(GL_COLOR_MATERIAL);
	glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
	
	gluLookAt (1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0);

	drawSocket ();
  glColor4f(1.0f, 0.0f, 0.0f, 1.0f);
  glPushMatrix();
    glTranslated(1.0, 1.0, 0.0);
    glRotatef(45, 1.0, 1.0, 1.0);
    drawCube();
  glPopMatrix();
  glDisable(GL_COLOR_MATERIAL);
}

void display (void) {
  GLfloat lightAmbient[] = {0.0, 0.0, 0.0, 1.0};
  GLfloat lightDiffuse[] = {1.0, 1.0, 1.0, 1.0};
  GLfloat lightSpecular[] = {1.0, 1.0, 1.0, 1.0};
  GLfloat lightPosition[] = {1.0, 1.0, 1.0, 0.0};

  GLfloat materialAmbient[] = {1.0f, 1.0f, 1.0f, 1.0f};
  GLfloat materialDiffuse[] = {1.0f, 1.0f, 1.0f, 1.0f};
  GLfloat materialSpecular[] = {0.0f, 0.0f, 0.0f, 1.0f};
  GLfloat materialEmission[] = {0.0f, 0.0f, 0.0f, 1.0f};

	glClearColor (0.6, 0.6, 0.65, 0.0);
  glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

  glMatrixMode (GL_PROJECTION);
  glLoadIdentity ();
  glFrustum(0.0, 400.0, 0.0, 400.0, 20.0, 24.0);
  glTranslated(0.0, 0.0, -22.0); 

  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();
 
  glLightfv(GL_LIGHT0, GL_AMBIENT, lightAmbient);
  glLightfv(GL_LIGHT0, GL_DIFFUSE, lightDiffuse);
  glLightfv(GL_LIGHT0, GL_SPECULAR, lightSpecular);
  glLightfv(GL_LIGHT0, GL_POSITION, lightPosition);

  glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, materialAmbient);
  glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, materialDiffuse);
  glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, materialSpecular);
  glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, materialEmission);
  glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 1.0); /* very low shininess */

  glEnable(GL_COLOR_MATERIAL);
  glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
  /* enables you to select material diffuse lighting property by glColor*() */
 
  drawMyObjects ();

  glutSwapBuffers ();
}

void reshape (int w, int h) {
  win_width = w;
  win_height = h;

  glViewport (0, 0, w, h);
}

void myinit (void) {

  glClearColor(0.3f, 0.3f, 0.3f, 1.0f);

 
  glEnable(GL_LIGHTING);
  glEnable(GL_LIGHT0);
  glEnable(GL_DEPTH_TEST);
  glEnable(GL_NORMALIZE);
}

void InitialGLUT (void) {
  int menu_idx;
  char title[] = "my window";

  win_width = WIN_SIZE_X;
  win_height = WIN_SIZE_Y;


  glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
  glutInitWindowSize (win_width, win_height);
  glutInitWindowPosition (0, 0);
  glutCreateWindow (title);

  myinit ();

  glutDisplayFunc (display);
  glutReshapeFunc (reshape);
  glutKeyboardFunc (keyboard);
  glutMouseFunc (mouseButton);
  glutMotionFunc (mouseMotion);


  menu_idx = glutCreateMenu (menu);
  glutSetMenu (menu_idx);
  glutAddMenuEntry ("mode 1", MODE_1);
  glutAddMenuEntry ("------", -1);
  glutAddMenuEntry ("mode 2", MODE_2);
  glutAddMenuEntry ("mode 3", MODE_3);
  glutAttachMenu (GLUT_RIGHT_BUTTON);
}

void main (int argc, char **argv) {
  glutInit (&argc, argv);
  InitialGLUT ();
  glutMainLoop ();
}
