/**************************************************
 *   File:     ModelViewer.cpp
 *   Author:   Dr. Dalton R. Hunkins     
 *   Date:     February 2009
 *
 *
 *  Modes of User Interaction
 *   GLUI Controls:
 *     List Box - file names in established folder
 *     Button   - close program
 *   Mouse:
 *     Left-Press and Drag in Display Window
 *        rotate the object about the x and y coordinate axes
 *   Keyboard: 
 *     Up Arrow   - "brighten" the light
 *     Down Arrow - "dim" the light
 *
**************************************************/
#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;
ObjModel         *model;

CGWorld     cgWorld;
Selection   selection;

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

char   modelDirectory[500];

string parentDirectory       = "OpenGLTutorials";	

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

// GLUI Control Handlers

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 == "obj") {                  
         if (model != NULL) 
            delete model;
         model = new ObjModel(modelDirectory, fileName);
         cgWorld.setModel(model);
      }              
   }              
}

void closeButtonHandler(int id) {
   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);   
                                                                           
}	

// CGWorld Callback Functions
void displayCGWorld() {
   cgWorld.display();
}

void reshapeCGWorld(int width, int height) {
   cgWorld.reshape(width, height);
}	

void mouseCGWorld(int button, int state, int x, int y) {
	cgWorld.mouse(button, state, x, y);
}

void mouseMotionCGWorld(int x, int y) {
	cgWorld.mouseMotion(x, y);
}

void specialKeyboardCGWorld(int key, int x, int y) {
	cgWorld.specialKeyboard(key, x, y);
}	 

void displaySelection() {
   selection.display();
}

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

    // Create File Browser
    fileBrowser = new GLUI_FileBrowser(mainPanel, "Open Obj File", 
                                       GLUI_PANEL_EMBOSSED, -1, fileBrowserHandler);                                       
    fileBrowser->fbreaddir(modelDirectory);  
    fileBrowser->set_allow_change_dir(false);     

    // Create Button
    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("Obj Model Viewer");     
    glutDisplayFunc(displayMain);
    glutReshapeFunc(reshapeMain);
    
    // Create Graphics Window
    cgWorld.createSubWindow(mainWindowHandle,
                            mainWindowWidth, mainWindowHeight, 2, 2, 60, 96); 
    glutDisplayFunc(displayCGWorld);
    glutReshapeFunc(reshapeCGWorld);
    glutMouseFunc(mouseCGWorld);
    glutMotionFunc(mouseMotionCGWorld);
    glutSpecialFunc(specialKeyboardCGWorld);
    cgWorld.init(black);    
                      
    // Create GLUI Controls Window
    selection.createSubWindow(mainWindowHandle,
                              mainWindowWidth, mainWindowHeight, 64, 5, 32, 50); 
    glutDisplayFunc(displaySelection);
    selection.init(mainClearColor);
    
    createGLUIInterface();
        
    try {
      glutMainLoop();
    }
    catch (ProgramExit) { 
    	cout << "Closing program" << endl;}
    return 0;
}