/* -*- 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 <viewit/wireframe.hh>
extern "C" {
#include <GL/gle.h>
}


/********************************************************************************
 *										*
 *				TPolyCone					*
 *										*
 *******************************************************************************/

TPolyCone::TPolyCone(unsigned int size)
	: __npoints(size), __point_array(new C3DDVector[size]), __radius_array(new double[size])
{;}


void TPolyCone::do_gl_draw()
{
	glePolyCone(__npoints,
			reinterpret_cast<double (*)[3] >(__point_array),
			NULL, 
			__radius_array);
}


C3DDVector* TPolyCone::get_point_vec() const
{
	return __point_array;
}


double* TPolyCone::get_radius_vec() const
{
	return __radius_array;
}
	 
	
unsigned int TPolyCone::size() const
{
	return __npoints;
}


/********************************************************************************
 *										*
 *				TWireFrameData					*
 *										*
 *******************************************************************************/


TWireFrameData::TWireFrameData()
	: __draw_components(LINES_AND_POINTS), __sphere_quad(gluNewQuadric())
{;}


TWireFrameData::~TWireFrameData()
{
	std::list<TPolyCone *>::const_iterator cbeg = __paths.begin();
	std::list<TPolyCone *>::const_iterator cend = __paths.end();	
	
	while (cbeg != cend) delete (*cbeg++);
	
	gluDeleteQuadric(__sphere_quad);
}


void TWireFrameData::add_node(const C3DFVector &location) 
{
 	__nodes.push_back(location);
}


void TWireFrameData::add_polycone(TPolyCone *polycone)
{
	__paths.push_back(polycone);
}	


void TWireFrameData::toggle_view() 
{
	__draw_components = (__draw_components == LINES_AND_POINTS ? ONLY_LINES : (__draw_components == ONLY_LINES ? ONLY_POINTS : LINES_AND_POINTS));
}		
		

bool TWireFrameData::do_handle_key_event(int key) 
{
	switch (key) {
	default: return false;
	}
	return true; 
}	


bool TWireFrameData::do_handle_command_event(PEventInfo info)
{
	switch (info->get_command()) {

	case EV_WIREFRAME_TOGGLE_VIEW: 
		toggle_view();
		break;
		
	default: 
		return false;
	}
	return true;	
}


void TWireFrameData::do_gl_draw(const TCamera& c) const
{
	// draw the polylines
	if (__draw_components & ONLY_LINES) {
		
		// at first draw the lines
		std::list<TPolyCone*>::const_iterator cbeg = __paths.begin();
		std::list<TPolyCone*>::const_iterator cend = __paths.end();		
		
		gleSetNumSides(10);
		gleSetJoinStyle(TUBE_JN_ROUND);

		while (cbeg != cend) {
			(*cbeg++)->do_gl_draw(); 
		}
	}

	// draw the unconnected knots
	if (__draw_components & ONLY_POINTS) {

		std::list<C3DFVector>::const_iterator nbeg = __nodes.begin();
		std::list<C3DFVector>::const_iterator nend = __nodes.end();		
		while (nbeg != nend) {
			glPushMatrix ();
			glTranslatef ( (*nbeg).x, (*nbeg).y, (*nbeg).z ); 
			gluSphere (__sphere_quad, 0.5, 10, 10);
			glPopMatrix();
			nbeg++;
		}
	}
}


bool TWireFrameData::do_export(FILE *f) const
{
	assert(f);
	
	bool success = true;
	
// 	std::list< TPolyLine* >::const_iterator ibeg = __lines.begin();
// 	std::list< TPolyLine* >::const_iterator iend = __lines.end();
	
	
// 	// export the polylines
// 	while (ibeg != iend && success)
// 		success = (*ibeg++)->do_export(f);
	

// 	// export the unconnected points
// 	if (__points && success)
// 		success = __points->do_export(f,true);
	    
 	return success;
}

/********************************************************************************
 *										*
 *				TWireFrame					*
 *										*
 *******************************************************************************/

TWireFrame::TWireFrame(const string& name)
	: TDrawable(name), __data(new TWireFrameData) 
{
	set_color1(C4DFVector(0.43, 1.0, 0.88, 1.0));
}
	  

TWireFrame::~TWireFrame() 
{
	if (__data) delete __data;
}


const char* TWireFrame::get_classname() const
{
	return WIREFRAME_CLASSNAME;
}


void TWireFrame::get_classname_list(list<string> *classlist) const
{
	if (classlist) {
		classlist->push_front(WIREFRAME_CLASSNAME);
		TDrawable::get_classname_list(classlist);
	}
}
	

void TWireFrame::add_node(const C3DFVector& location)
{
	__data->add_node(location);
}


void TWireFrame::add_polycone(TPolyCone *polycone)
{
	__data->add_polycone(polycone);
}


bool TWireFrame::do_handle_key_event(int key) 
{
	if (!__data->do_handle_key_event(key)) 
		return TDrawable::do_handle_key_event(key);
	return true; 
}	
	
bool TWireFrame::do_handle_command_event(PEventInfo info)
{
	if (__data->do_handle_command_event(info))
		return true;
	
	return TDrawable::do_handle_command_event(info);
}


void TWireFrame::do_gl_draw(const TCamera& c) const
{
	glColor4f(get_color1().x, get_color1().y, get_color1().z, get_color1().a);
	__data->do_gl_draw(c);	
}

bool TWireFrame::do_export(FILE *f)const
{
	assert(f);
	fprintf(f,"WireFrame\n");
	return __data->do_export(f);
}

