/* window.h
 */


#ifdef GL
  #include <GL/gl.h>
  #include <GL/glu.h>
  #include <GL/glut.h>
#endif

#ifndef WINDOW_H
#define WINDOW_H

#include "vector.h"
#include "main.h"


void GLUTdisplay();
void GLUTidle();
void GLUTreshape( int x, int y );
void GLUTmouseAction( int button, int state, int x, int y );
void GLUTmouseMotion( int x, int y );
void GLUTkeyAction( unsigned char c, int x, int y );


typedef enum { PERSPECTIVE, ORTHOGRAPHIC } ProjectionType;


class window {

  void registerWindow( int windowId );

public:

  int windowId;
  int xdim, ydim;

  ProjectionType projection;

  vector eye, lookat, updir;	// model transformation

  float  fovy;			// perspective projection

  float horizUnits;		// orthographic projection
  float centreX, centreY;	//   left = centreX - horizUnits/2
  float near, far;		//   bottom = centreY - horizUnits/2 * ydim/xdim

  virtual void display() = 0;
  virtual void idle() {};
  virtual void mouseAction( int button, int state, int x, int y ) {};
  virtual void mouseMotion( int x, int y ) {};
  virtual void keyAction( unsigned char key, int x, int y ) {};

  virtual void reshape( int width, int height ) {
#ifdef GL
    xdim = width;
    ydim = height;
    glViewport( 0, 0, width, height );
    glutPostRedisplay();
#endif    
  }

  void setupProjection() {
#ifdef GL
    glMatrixMode( GL_PROJECTION );
    glLoadIdentity();
    if (projection == PERSPECTIVE)
      gluPerspective( fovy, (float) xdim / (float) ydim, 1, 1000 );
    else 
      glOrtho( centreX - horizUnits/2,
	       centreX + horizUnits/2,
	       centreY - horizUnits/2 * (float) ydim / (float) xdim,
	       centreY + horizUnits/2 * (float) ydim / (float) xdim,
	       near, far );

    glMatrixMode( GL_MODELVIEW );
    glLoadIdentity();
    gluLookAt( eye.x, eye.y, eye.z,
	       lookat.x, lookat.y, lookat.z,
	       updir.x, updir.y, updir.z );
#endif    
  }

  window( int x, int y, int width, int height, char *title ) {
#ifdef GL
    xdim = width;
    ydim = height;

    eye = vector(0,0,50);	// model view
    lookat = vector(0,0,0);
    updir = vector(0,1,0);

    projection = PERSPECTIVE;	// perspective params
    fovy = 30;

    horizUnits = 1;		// orthographic params
    centreX = 0; centreY = 0; 
    near = 0; far = 1000;

    glutInitWindowPosition( x, y );
    glutInitWindowSize( xdim, ydim );
    windowId = glutCreateWindow( title );
    registerWindow( windowId );
    glutSetWindow( windowId );
    glutDisplayFunc( GLUTdisplay );
    glutReshapeFunc( GLUTreshape );
    glutMouseFunc( GLUTmouseAction );
    glutMotionFunc( GLUTmouseMotion );
    glutKeyboardFunc( GLUTkeyAction );
    glutIdleFunc( GLUTidle );
#endif    
  }

  void redraw() {
#ifdef GL
    if (outputGraphics) {
      glutSetWindow( windowId );
      glutPostRedisplay();
    }
#endif
  }
};

#endif
