/**************************************************
 *   File:     TextureMethods.cpp
 *   Author:   Dr. Dalton R. Hunkins     
 *   Date:     February 2009
 *
 *
 *  Modes of User Interaction
 *   GLUI Controls:
 *     List Box:    
 *        file names within established folder
 *     Group of Spinners (Set Base Color):
 *        set the red, green and blue values of the geometry color
 *     Group of Radio Buttons (Set Method):
 *        select between the texture methods decal and modulate
 *        or no mapping
 *     Check Box:
 *        enable/disable lighting
 *     Button:
 *        close the program
**************************************************/
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>
#include <GL/glui.h>
#include <iostream>
using namespace std;


#include "CGWorld.h"

#include "Selection.h"

class ProgramExit { };

GLUI_FileBrowser *fileBrowser;
GLUI_Panel       *mainPanel;
GLUI_Spinner     *redSpinner;
GLUI_Spinner     *greenSpinner;
GLUI_Spinner     *blueSpinner;
GLUI_RadioGroup  *methodGroup;
GLUI_Checkbox    *checkbox;

CGWorld     cgWorld;
Selection   selection;

int mainWindowHandle;

float mainClearColor[] = {0.75, 0.75, 1.00, 1.00};

char   imageMapDirectory[500];

string parentDirectory       = "OpenGLTutorials";	

void setPaths(string pathName) {
	string imagePath;
	
	if (pathName[0] == '/') {
       pathName = pathName.substr(10, pathName.length());
       imagePath = pathName.substr(0,1) + ":/";
	   pathName = pathName.substr(2, pathName.length());
	}   
    int position = pathName.find(parentDirectory, 0);
    pathName = pathName.substr(0, position+parentDirectory.length());
    imagePath += pathName + "/Resources/ImageMaps/";
    for (unsigned i=0; i<imagePath.length(); i++)
       imageMapDirectory[i] = imagePath[i];
    imageMapDirectory[imagePath.length()] = 0;
}

// GLUI Control Handlers
void void fileBrowserHandler(int id) {
   string fileName = fileBrowser->get_file();
   if (fileName[0] != '.') {
      int position = fileName.find(".", 0);
      string fileExtension = fileName.substr(position+1, fileName.length());
      if (fileExtension == "bmp") {                  
         cgWorld.setImageMap(imageMapDirectory, fileName);
         methodGroup->set_int_val(1);
      }              
   }              
}

void spinnerHandler(int id) {
   switch (id) {
       case 1 :
          cgWorld.setRed(redSpinner->get_float_val());
          break;
       case 2 :
          cgWorld.setGreen(greenSpinner->get_float_val());
          break;
       case 3 :
          cgWorld.setBlue(blueSpinner->get_float_val());
          break;
   }
}

void radioButtonHandler(int id) {
   switch (methodGroup->get_int_val()) {
          case 0 :
               cgWorld.setTextureMethod(MODULATE);
               break;
          case 1 : 
               cgWorld.setTextureMethod(DECAL);
               break;
          case 2 :               
               cgWorld.setTextureMethod(NONE);
               break;
   }            
}

void checkBoxHandler( int control) {
	cgWorld.setLightingMode(checkbox->get_int_val() == 1);
}

void closeButtonHandler(int value) {
   throw ProgramExit();
}

void displayMain() {
    glClearColor(mainClearColor[0], mainClearColor[1], mainClearColor[2], mainClearColor[3]);  
    glClear(GL_COLOR_BUFFER_BIT);
    glutSwapBuffers();
}
void reshapeMain(int width, int height) {
   glutSetWindow(cgWorld.getWindowHandle());
   glutPositionWindow((cgWorld.getCornerX()*width)/100,
                      (cgWorld.getCornerY()*height)/100);
   glutReshapeWindow((cgWorld.getWidth()*width)/100,
                     (cgWorld.getHeight()*height)/100);  
                     
   glutSetWindow(selection.getWindowHandle());
   glutPositionWindow((selection.getCornerX()*width)/100,
                      (selection.getCornerY()*height)/100);
   glutReshapeWindow((selection.getWidth()*width)/100,
                     (selection.getHeight()*height)/100);   
                                                                           
}	

void displayCGWorld() {
   cgWorld.display();
}

void displaySelection() {
   selection.display();
}
void createGLUIInterface() {    
    // Create Main Panel
    GLUI *gluiSubWindow = GLUI_Master.create_glui_subwindow(selectionWindow.getWindowHandle(), 					                                        GLUI_SUBWINDOW_TOP );
    mainPanel = new GLUI_Panel(gluiSubWindow, "", GLUI_PANEL_NONE);

    // Create File Browsert
    fileBrowser = new GLUI_FileBrowser(mainPanel, "Open Bmp File", 
                                       GLUI_PANEL_EMBOSSED, -1, fileBrowserHandler);                                       
    fileBrowser->fbreaddir(imageMapDirectory);  
    fileBrowser->set_allow_change_dir(false);     

    // Create New Panel
    GLUI_Panel *colorPanel = new GLUI_Panel(mainPanel, "Set Base Color",
     							                  GLUI_PANEL_EMBOSSED);

    // Create Color Spinners
    redSpinner = gluiSubWindow->add_spinner_to_panel(colorPanel, "Red",
                 GLUI_SPINNER_FLOAT, NULL, 1, spinnerHandler);
    redSpinner->set_float_val(1.00);
    redSpinner->set_float_limits(0.00, 1.00, GLUI_LIMIT_CLAMP);

    greenSpinner = gluiSubWindow->add_spinner_to_panel(colorPanel, "Green",
                   GLUI_SPINNER_FLOAT, NULL, 2, spinnerHandler);
    greenSpinner->set_float_val(1.00);
    greenSpinner->set_float_limits(0.00, 1.00, GLUI_LIMIT_CLAMP);

    blueSpinner = gluiSubWindow->add_spinner_to_panel(colorPanel, "Blue", 
                  GLUI_SPINNER_FLOAT, NULL, 3, spinnerHandler);
    blueSpinner->set_float_val(1.00);
    blueSpinner->set_float_limits(0.00, 1.00, GLUI_LIMIT_CLAMP);

    GLUI_Panel *methodPanel = new GLUI_Panel(mainPanel, "Select Method", GLUI_PANEL_EMBOSSED);
    
    // Create Radio Button Group
    methodGroup = new GLUI_RadioGroup(methodPanel, NULL, -1, radioButtonHandler);
    new GLUI_RadioButton( methodGroup, "Modulate");
    new GLUI_RadioButton( methodGroup, "Decal" );
    new GLUI_RadioButton( methodGroup, "No Mapping" );
    methodGroup->set_int_val(2);
    
    // Create CheckBox and Button
    checkbox = new GLUI_Checkbox(mainPanel, "Enable Lighting", NULL, -1, checkBoxHandler);
    checkbox->set_int_val(1);

    gluiSubWindow->add_button_to_panel(mainPanel, "Close Program", -1, closeButtonHandler);
}

int main (int argc, char** argv) {

    string pathName = argv[0];
    setPaths(pathName);
    
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);

    int mainWindowWidth  = 800;
    int mainWindowHeight = 500;

    // Create Main Window
    glutInitWindowPosition(10, 10);
    glutInitWindowSize(mainWindowWidth, mainWindowHeight);
    mainWindowHandle = glutCreateWindow("Texture Methods");     
    glutDisplayFunc(displayMain);
    glutReshapeFunc(reshapeMain);
    
    // Create Graphics Subwindow
    cgWorld.createSubWindow(mainWindowHandle,
                            mainWindowWidth, mainWindowHeight, 2, 2, 60, 96); 
    glutDisplayFunc(displayCGWorld);
    cgWorld.init(black);    
                      
    // Create GLUI Subwindow
    selection.createSubWindow(mainWindowHandle,
                              mainWindowWidth, mainWindowHeight, 64, 5, 32, 85); 
    glutDisplayFunc(displaySelection);
    selection.init(mainClearColor);
    
    createGLUIInterface();
        
    try {
      glutMainLoop();
    }
    catch (ProgramExit) { 
    	cout << "Closing program" << endl;}
    return 0;
}