#include "exp004mouse.h"
#include "exp004processhits.h"
#include "../view/exp004geometry.h"
#include "../view/exp004state0.h"
#include "../util/check_error.h"
#include <GL/glut.h>
#include <stdio.h>

#define SIZE 500
#define N 3

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

  if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
    {

      /*
       * "Specify the array to be used for the returned hit records
       * with glSelectBuffer () [Redbook]."
       */
      GLuint select_buf[SIZE];
      glSelectBuffer (SIZE, select_buf);

      /*
       * "Enter selection mode by specifying GL_SELECT with
       * glRenderMode () [Redbook]."
       */
      glRenderMode (GL_SELECT);

      /*
       * "Initialize the name stack using glInitNames () and glPush
       * Names () [Redbook]."
       */
      glInitNames ();
      glPushName (0);

      /*
       * "Define the viewing volume you want to use for selection.
       * Usually this is different from the viewing volume you
       * originally used to draw the scene, so you probably want to
       * save and then restore the current transformation state with
       * glPushMatrix () and glPopMatrix () [Redbook]."
       */
      glMatrixMode (GL_PROJECTION);
      glPushMatrix ();
      glLoadIdentity ();

      GLint viewport[4];
      glGetIntegerv (GL_VIEWPORT, viewport);

      gluPickMatrix ((GLdouble) x,
		     (GLdouble) (viewport[3] - y),
		     N,
		     N,
		     viewport);

      gluOrtho2D(exp004state0.ortho.min_x,
		 exp004state0.ortho.max_x,
		 exp004state0.ortho.min_y,
		 exp004state0.ortho.max_y);      

      /*
       * "Alternately issue primitive drawing commands and commands to
       * manipulate the name stack so that each primitive of interest
       * has appropriate names assigned [Redbook]."
       */
      exp004geometry (GL_SELECT);

      glMatrixMode (GL_PROJECTION);      
      glPopMatrix ();
      glutSwapBuffers ();

      /*
       * "Exit selection mode and process the returned selection data
       * (the hit records) [Redbook]."
       */
      GLint hits = glRenderMode (GL_RENDER);
      check_error (__FILE__, __LINE__);
      
      /* "process hits from selection mode rendering [Angel,2008]." */
      exp004processhits (hits, select_buf);
      
      /* "normal render [Angel,2008]." */      
      glutPostRedisplay ();
    }

  return;
}