/* -*- mia-c++ -*-
 *
 * This file is part of viewitgui - a library and program for the
 * visualization of 3D data sets. 
 *
 * Copyright (c) Leipzig, Madrid 1999-2013 Mirco Hellmann, Gert Wollny
 *
 * viewitgui is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * viewitgui is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with viewitgui; if not, see <http://www.gnu.org/licenses/>.
 */


#include <gtkmm/main.h>
//#include <glade/glade.h>
#include <sstream>


// windows
#include "WinMain.hh"
#include "WinStatus.hh"
#include "WinScene.hh"
#include "WinOptions.hh"

#include "SignalHandler.hh"
#include "userini.hh"

#include <viewit/glviewer.hh>



#define VIEWIT_INI_FILENAME "viewit.conf.xml"


const SProgramDescription g_description = {
        {pdi_group, "Visualization"}, 
	{pdi_short, "Visualization of 3D data"}, 
	{pdi_description, "This program is used to visualize 3D data sets and deformations."}
}; 


SignalHandler *viewit_signal_handler	= NULL;
XMLini *inifile				= NULL;
ViewitObjects *vobjects			= NULL;
CEventQueue *pending_events		= NULL;
int testwert = 100;

int main(int argc, char *argv[]) 
{  
  /*
#if defined(ENABLE_NLS)
	bindtextdomain (GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR);
	textdomain (GETTEXT_PACKAGE);
	
#endif //ENABLE_NLS
  */
	Gtk::Main m(argc, argv);

	// Init gtkglextmm.
	Gtk::GL::init(argc, argv);
	
	// Init glade
	//glade_init();
	
	// now for the command line parameters ...
	std::string src_mesh_filename;
	std::string vectorfield_filename;
	std::string scene_display_name(getenv("DISPLAY")); 
	//	std::string main_display_name(getenv("DISPLAY"));
	
	CCmdOptionList options(g_description);
	options.add(make_opt(src_mesh_filename, "src-mesh", 's', "mesh to be visualized", 
			     CCmdOptionFlags::input, &CMeshIOPluginHandler::instance())); 
	options.add(make_opt(vectorfield_filename, "vectorfield",  'v', "vector field describing the mesh deformation", 
			     CCmdOptionFlags::input, &C3DTransformationIOPluginHandler::instance())); 
	
	if (options.parse(argc, argv) != CCmdOptionList::hr_no)
		return EXIT_SUCCESS; 
	
	// read user specific information stored in ~/.viewit/
	std::string inipath	= Glib::get_home_dir() + "/.viewit/";
	std::string syscommand	= "mkdir -p " + inipath;

	
	if (!system(syscommand.c_str())) {		
		inifile = new XMLini();
		syscommand = inipath + VIEWIT_INI_FILENAME;
		if (inifile->read_from_file(syscommand)) {
			std::cout << "Warning: unable to read config file " << syscommand << "!\n" << std::flush;
		}
	} 
	

	// signal handler for the comunication between the different windows

	viewit_signal_handler	= new class SignalHandler;
	
	// get the plugin_paths from the configfile

	std::list<std::string> plugin_search_paths;
	std::string section = "PluginSearchPath";
	std::string key = "path0";
	std::string value;
	int pathidx = 1;
	
	while (inifile->get_value(section,key,value)) {
		plugin_search_paths.push_back(value);
		char buffer[10];
		sprintf(buffer,"path%d",pathidx++);
		key = buffer;
	}
	
	if (plugin_search_paths.empty()) {
		plugin_search_paths.push_back(inipath + string("plugins"));
	}
	
	PGLViewer glviewer(new TGLViewer(NULL));

	Glib::RefPtr<Gdk::Display> 	scene_display = Gdk::Display::open(scene_display_name.c_str());
	Glib::RefPtr<Gdk::Screen> 	scene_screen = scene_display->get_default_screen ();
	
	
	
	
		
	pending_events		= new CEventQueue();
 	pending_events->signal_handle_event().connect(sigc::mem_fun(*glviewer,&TGLViewer::handle_event));
	
	vobjects		= new ViewitObjects();
	
	// Instantiate and run the application.

	std::cerr << "create winmain" << endl;
	WinMain *WMain		= new WinMain(glviewer);
	std::cerr << "done" << endl;
	//	WMain->set_screen(main_screen);
		
	viewit_signal_handler->WinMain_hide_notification().connect( sigc::mem_fun(*WMain, &WinMain::on_WinMain_hide_notification) );
	viewit_signal_handler->WinMain_objectmap_changed().connect( sigc::mem_fun(*WMain, &WinMain::on_WinMain_objectmap_changed) );
	
	std::cerr << "create winstatus" << endl;
	WinStatus *WStatus	= new class WinStatus();
	//	WStatus->set_screen(main_screen);
	
	viewit_signal_handler->WinStatus_set_visibility().connect( sigc::mem_fun(*WStatus, &WinStatus::on_WinStatus_set_visibility) );
	viewit_signal_handler->WinStatus_append_text().connect( sigc::mem_fun(*WStatus, &WinStatus::on_WinStatus_append_text) );
	
	
	std::cerr << "create winoptions" << endl;
	WinOptions *WOptions	= new class WinOptions();
	//	WOptions->set_screen(main_screen);
	
	viewit_signal_handler->WinOptions_set_visibility().connect( sigc::mem_fun(*WOptions, &WinOptions::on_WinOptions_set_visibility) );
	viewit_signal_handler->WinOptions_set_object().connect( sigc::mem_fun(*WOptions, &WinOptions::on_WinOptions_set_object) );
	viewit_signal_handler->WinOptions_set_vectorfield().connect( sigc::mem_fun(*WOptions, &WinOptions::on_WinOptions_set_vectorfield) );
	viewit_signal_handler->WinOptions_set_viewer().connect( sigc::mem_fun(*WOptions, &WinOptions::on_WinOptions_set_viewer) );
	
	
	
	
	std::cerr << "create winscene" << endl;
	WinScene *WScene	= new class WinScene(scene_screen, glviewer);
	
	viewit_signal_handler->WinScene_detach().connect( sigc::mem_fun(*WScene, &WinScene::on_WinScene_detach) );
	viewit_signal_handler->WinScene_resize().connect( sigc::mem_fun(*WScene, &WinScene::on_WinScene_resize) );
	viewit_signal_handler->WinScene_press_key().connect( sigc::mem_fun(*WScene, &WinScene::on_WinScene_press_key) );
	viewit_signal_handler->WinScene_set_visibility().connect( sigc::mem_fun(*WScene, &WinScene::on_WinScene_set_visibility) );


	std::cerr << "load src mesh?" << endl;
	// start the main loop
	if (src_mesh_filename.size() > 0)
		WMain->add_object_mesh(src_mesh_filename, "source mesh", true);
	
	std::cerr << "load vectrofield?" << endl;
	if (vectorfield_filename.size() > 0)
		WMain->add_vectorfield(vectorfield_filename, "vectorfield");
	



	cerr << "run main loop" << endl; 
	WScene->show(); 
	
	m.run(*WMain);

	delete WOptions;
	// delete WScene FIXME:; Obscure segfault at program exit
	WScene->save_state();
	
	delete WStatus;
	delete WMain;
	
	delete pending_events;
	delete viewit_signal_handler;
	delete vobjects;
	
	std::string fn = inipath + VIEWIT_INI_FILENAME;
	
	inifile->write_to_file(fn);
	delete inifile;
		
	return 0;
}
