/* -*- 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 __smarties_hh
#define __smarties_hh

#include <memory>
#include <viewit/drawable.hh>
#include <GL/glu.h>

class CShape;
class CShading; 

#define SMARTIES_CLASSNAME "TSmarties"

/**
   Ths smarty is an ellisoide shape that corresponds to a 3x3 tensor describing, e.g. diffusion patterns.
   It will be colored based on the main axis direction and its size corresponds to the tensor "magnitute"   
*/
class TSmarty {
public:
	/** initialze a smarty with its position 
	    \param position  the position of the center of the smarty
	    \param cshape a shaping policy
	    \param cshading a shadingpolicy
	 */
	TSmarty(const C3DFVector& position, std::shared_ptr<CShape> cshape, std::shared_ptr<CShading> shading);
	
	/// copy constructor
	TSmarty(const TSmarty& org);

	/// copy constructor
	TSmarty& operator = (const TSmarty& org);
		
	/// clean up the data
	~TSmarty();
	
	/** prepare the smarty for drawing */
	virtual void pre_draw();
	
	/** clean up after drawing */
	virtual void post_draw();
	
	/** create the neccessary GL-instances */
	virtual void gl_attach();
	
	/** remove the neccessary GL-instances */
	virtual void gl_detach();
	
	bool operator == (const TSmarty& other) {
		return m_position == other.m_position;
	}
	
	bool operator != (const TSmarty& other) {
		return ! (*this == other); 
	}

private:
	C3DFVector  m_position; 
	std::shared_ptr<CShape> m_shape; 
	std::shared_ptr<CShading> m_shading; 
};


/** this is the "official" drawable, that handles the smarties */
class TSmarties : public TDrawable {
public:
	TSmarties(const string& name);
	~TSmarties();
	
	void add_smarty(TSmarty *smarty);
	void remove_smarty(TSmarty *smarty);
	
	void increase_smarty_number();
	void decrease_smarty_number();
	
	virtual void gl_attach();
	virtual void gl_detach();
	virtual const char* get_classname() const;
	virtual void get_classname_list(list<string> *classlist) const;
	
protected:
	virtual void do_gl_draw(const TCamera& c) const; 
	virtual bool do_handle_key_event(int key);
	virtual bool do_handle_command_event(PEventInfo info);
	

private:
	enum EDrawStepType  {
		dst_selection,
		dst_forward,
		dst_backward
 	};
	
	
	GLUquadricObj *		m_qobj;
 	GLuint			m_GLSphereDrawList;
	std::list<TSmarty *>	m_smarties;
	unsigned int		m_draw_smarty_step;
	EDrawStepType		m_draw_smarty_step_kind;
	
};

#endif
