// textkbd.cpp
// VERSION 2
// Glenn G. Chappell
// 6 Sep 2012
//
// For CS 381 Fall 2012
// GLUT Text & Keyboard Demo

// OpenGL/GLUT includes - DO THESE FIRST
#include <cstdlib>       // Do this before GL/GLUT includes
using std::exit;
#ifndef __APPLE__
# include <GL/glut.h>    // GLUT stuff, includes OpenGL headers as well
#else
# include <GLUT/glut.h>  // Apple puts glut.h in a different place
#endif

// Other includes
#include "lib381/bitmapprinter.h"
                         // For class BitmapPrinter
#include <sstream>
using std::ostringstream;
#include <iostream>
using std::cout;
using std::cerr;
using std::endl;


// Global variables
// Keyboard
const int ESCKEY = 27;         // ASCII value of Escape

// Window/viewport
const int startwinsize = 600;  // Start window width & height (pixels)

// Scene
bool showsquare;               // True if big square displayed
double redness;                // Red component of big square color


// myDisplay
// The GLUT display function
void myDisplay()
{
    glClearColor(0.7f, 0.7f, 0.7f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);

    // Draw objects
    if (showsquare)
    {
        glColor3d(redness, 0.3, 0.3);
        glBegin(GL_QUADS);
            glVertex2d(-0.7,-0.7);
            glVertex2d( 0.7,-0.7);
            glVertex2d( 0.7, 0.7);
            glVertex2d(-0.7, 0.7);
        glEnd();
    }
    glColor3d(0.3, 0.9, 0.3);
    glBegin(GL_QUADS);
        glVertex2d(-0.85,0.5 );
        glVertex2d(-0.5 ,0.5 );
        glVertex2d(-0.5 ,0.85);
        glVertex2d(-0.85,0.85);
    glEnd();
    glColor3d(0.3, 0.3, 0.9);
    glBegin(GL_QUADS);
        glVertex2d(0.85,-0.5 );
        glVertex2d(0.5 ,-0.5 );
        glVertex2d(0.5 ,-0.85);
        glVertex2d(0.85,-0.85);
    glEnd();

    // Draw documentation
    glLoadIdentity();
    glMatrixMode(GL_PROJECTION);  // Set up simple ortho projection
    glPushMatrix();
    glLoadIdentity();
    gluOrtho2D(-1., 1., -1., 1.);
    glColor3d(0., 0., 0.);        // Black text
    BitmapPrinter p(-0.9, 0.9, 0.1);
    p.print("This is bitmap text");
    ostringstream ostr;
    ostr << (2+3)*14;
    p.print("A number converted to a string: " + ostr.str());
    p.print("Space    Toggle big square");
    p.print("<- ->    Change red component of big square color");
    p.print("Esc      Quit");
    glPopMatrix();                // Restore prev projection
    glMatrixMode(GL_MODELVIEW);

    glFlush();
}


// myIdle
// The GLUT idle function
void myIdle()
{
    // Print OpenGL errors, if there are any (for debugging)
    static int error_count = 0;
    if (GLenum err = glGetError())
    {
        ++error_count;
        cerr << "OpenGL ERROR " << error_count << ": "
             << gluErrorString(err) << endl;
    }
}


// myKeyboard
// The GLUT keyboard function
void myKeyboard(unsigned char key, int x, int y)
{
    switch (key)
    {
    case ESCKEY:  // Esc: quit
        exit(0);
        break;
    case ' ':     // Space: toggle square
        showsquare = !showsquare;
        glutPostRedisplay();
        break;
    }
}


// mySpecial
// The GLUT special function
void mySpecial(int key, int x, int y)
{
    switch (key)
    {
    case GLUT_KEY_RIGHT:  // -> increase red
        redness += 0.1;
        if (redness > 1.)
            redness = 1.;
        glutPostRedisplay();
        break;
    case GLUT_KEY_LEFT:   // <- decrease red
        redness -= 0.1;
        if (redness < 0.)
            redness = 0.;
        glutPostRedisplay();
        break;
    }
}


// init
// Initialize GL states & global data
// Called by main after window creation
void init()
{
    // Scene
    showsquare = true;
    redness = 0.7;

    // GL stuff
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluOrtho2D(-1., 1., -1., 1.);

    glMatrixMode(GL_MODELVIEW);  // Always go back to model/view mode
}


int main(int argc, char ** argv)
{
    // Initialize OpenGL/GLUT
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);

    // Make a window
    glutInitWindowSize(startwinsize, startwinsize);
    glutInitWindowPosition(50, 50);
    glutCreateWindow("CS 381 - GLUT Text & Keyboard Demo");

    // Initialize GL states & register GLUT callbacks
    init();
    glutDisplayFunc(myDisplay);
    glutIdleFunc(myIdle);
    glutKeyboardFunc(myKeyboard);
    glutSpecialFunc(mySpecial);

    // Do something
    glutMainLoop();

    return 0;
}

