/* -*- 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/>.
 */


#ifndef __glviewer_hh
#define __glviewer_hh

#include <viewit/event.hh>
#include <viewit/camera.hh>
#include <viewit/drawable.hh>
#include <vector>
#include <memory>

#include <mia.hh>
using namespace mia; 



class CSnapshotClient; 



using namespace std; 

/** This is the main viewer class 
    \todo add a function to load a deformation field
*/

class TGLViewer: public TEventHandler {
public:
	
	/** construct the viewer 
	    \param deform a deformation field zu be visualized
	    \todo remove this initialisation with a vector field
	*/
	TGLViewer(P3DTransformation deform);
	

	TGLViewer(const TGLViewer& deform) = delete;
	TGLViewer& operator = (const TGLViewer& deform) = delete;
	/** the destructor cleans up the data*/
	~TGLViewer();
	
	
	/** add a new visualisation object to the viewer 
	    \param new_object the new drawable to be added 
	 */
	int add_object(TDrawable *new_object);
	
	/** removes an object from the viewer 
	    \param identifier is the name of drawable to be removed
	 */
	bool remove_object(const string& identifier);
	
	/** re-initializes the viewer with the given vectorfield
	    \param pointer to a vectorfield (NULL is possible)
	*/
	void reinit(P3DTransformation deform);
	
	/** \returns name of the currently selected object */
	const string get_current_selected() const;
	
	
	/** \returns a vector of al the object names available in the viewer */
	vector<string> *get_object_list() const;
	
	/** \returns a map containing the object names (key) and the corresponding object pointer (value) */
	const TDrawMap *get_object_map() const;
	
	
	/** select a certain drawable
	    \identifier name of the drawable to be selected 
	*/
	void select(const string& identifier); 

	
	/** initialize the OpneGL context */
	void gl_attach();
	
	/** detach from OpenGL */
	void gl_detach();
	
	/** draw the actual scene */
	void gl_draw();
	
	/** change the size of the output window
	    \param width new width
	    \param height new height
	*/
	void reshape(int width, int height);
	

	/** toggle movie recording on/off
	    \todo replace this by two functions start/stop movie 
	*/
	void toggle_movie_mode();
	
	/** \returns whether we are in movie mode */
	bool in_movie_mode()const;
	
	/** \returns the value for the rotation speed */
	float get_rotation_speed();
	
	/** set the speed of the rotation
	    \param speed 
	*/
	void set_roataion_speed(float speed);
	
	/** \returns the value of the background brightness */
	float get_background_brightness();
	
	/** set the background brigthness
	    \param brightness value
	*/
	void set_background_brightness(float brightness);

	
	/** this function should be called if the application is idle */
	bool idle();
	
	/** \returns the size of the viewport */
	C2DBounds get_viewport()const; 
	
	const TColor& get_bg_color() const;
	
	void set_bg_color(const TColor& new_bg);
	
	/** an unfinished function to handle scene loading
	    \remark might go away and be replaced by something else
	*/
	bool set_parse_object(const std::string& tag, const std::string& key);
	
	/** the main event handler function
	 \param event an event to be handled -> event->what is set to TEventHandler::ev_nothing if the event was handled
	 \returns (obsolete)
	*/
	bool handle_event(event_t *event);
protected:
	/** handled the key events */
	bool do_handle_key_event(int key);
	
	/** handles mouse events */
	bool do_handle_mouse_event(int button,int x, int y);
	
	/** handles command events */
	bool do_handle_command_event(PEventInfo info);
private:
	class TData *data;
};

typedef std::shared_ptr<TGLViewer> PGLViewer; 

#endif
