/* -*- 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/measure.hh>
#include <viewit/gltext.hh>

#include <mia.hh>
using namespace mia; 


#include <memory>
#include <iostream>
#include <GL/gl.h>
#include <viewit/arrow.hh>

using namespace std; 




class TMeasureData {
	friend class TMeasure;
	
public: 
	TMeasureData(TCamera *c,P3DTransformation field);
	~TMeasureData(); 

	void draw_decoration(const C2DBounds& viewport,const TGLText& writer, const TColor& color);
	bool do_handle_mouse_event(int button,unsigned int x, unsigned int y); 
	void toggle_display_decoration();
	void select();
private:
	TCamera *m_camera; 
	C3DFVector m_loc3d;
	bool m_do_display_decoration;
	P3DTransformation m_field;
	TArrowListGrow arrow_list; 
};

TMeasureData::TMeasureData(TCamera *c, P3DTransformation field):
	m_camera(c),
	m_loc3d(0.0,0.0,0.0),
        m_do_display_decoration(true), 
	m_field(field),
	arrow_list(string("arrow_list"),TColor(0.5,0.5,1.0,1.0),TColor(1.0,0.5,0.5,1.0) ,field)
{	
}

TMeasureData::~TMeasureData()
{
}

void TMeasureData::toggle_display_decoration()
{
	m_do_display_decoration = !m_do_display_decoration; 
}

void TMeasureData::draw_decoration(const C2DBounds& viewport,const TGLText& writer, const TColor& color)
{
	if (!m_do_display_decoration)
		return; 

	int x = m_camera->get_viewport().x;
	int y = m_camera->get_viewport().y;	
	
	glColor4f(0.0f,.5f,0.0f,0.0f);
	glBegin(GL_QUADS);
	glVertex2f(x -   5.0f,y - 10.0f);
	glVertex2f(x - 400.0f,y - 10.0f);
	glVertex2f(x - 400.0f,y - 30.0f);
	glVertex2f(x-    5.0f,y - 30.0f);
	glEnd();
	
	char value[400]; 
	
	snprintf(value,400," < %5.1f, %5.1f, %5.1f >  ",m_loc3d.x, m_loc3d.y, m_loc3d.z);
	glColor3fv(&color.x);
	writer.write(x - 390, y - 28, value);
	
	if ( m_field && m_loc3d.x >= 0.0) {
		const C3DTransformation& vf = *m_field;
		C3DFVector v = vf(m_loc3d);
		
		glColor4f(0.0f,.5f,0.0f,0.0f);
		glBegin(GL_QUADS);
		glVertex2f(x - 400.0f,y - 30.0f);
		glVertex2f(x-    5.0f,y - 30.0f);
		glVertex2f(x -   5.0f,y - 50.0f);
		glVertex2f(x - 400.0f,y - 50.0f);


		glEnd();

		
		snprintf(value,400," < %5.2f, %5.2f, %5.2f  > norm: %5.2f ",v.x, v.y, v.z, v.norm());
		glColor3fv(&color.x);
		writer.write(x - 390, y - 48, value);
	}
}

bool TMeasureData::do_handle_mouse_event(int button,unsigned int x, unsigned int y)
{
	m_loc3d = m_camera->get_spacecoord(x,m_camera->get_viewport().y - y);
	return true;
}

TMeasure::TMeasure(const string& name,TCamera *c,P3DTransformation field):
	TDrawable(name),
	data(new TMeasureData(c,field))
{
	data->arrow_list.show();
	light_on();
}

TMeasure::~TMeasure()
{
	delete data; 
}

const char* TMeasure::get_classname() const 
{
	return MEASURE_CLASSNAME;
}

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

void TMeasure::set_vectorfield(P3DTransformation field)
{
	data->m_field = field;
}

bool TMeasure::do_handle_mouse_event(int button,int x, int y)
{
	if (is_selected()) {
		data->do_handle_mouse_event(button,x,y);
		return (button == 0);
	}
	return false;
}
	
bool TMeasure::handle_event(event_t *event)
{
	if (!TDrawable::handle_event(event))
		return data->arrow_list.handle_event(event);
	return true; 
}

bool TMeasure::do_handle_key_event(int key)
{
	switch (key) {
	case 'd':
		data->toggle_display_decoration();
		break; 
	case ' ':
		if (is_selected()) {
			if (data->m_loc3d.x > 0) {
				data->arrow_list.add_vector(data->m_loc3d);
			}
		}
		break; 
		
	default:
		return TDrawable::do_handle_key_event(key);
	}
	return true; 	

}

void TMeasure::do_gl_draw(const TCamera& c) const
{
	data->arrow_list.gl_draw(c);
}
void TMeasure::draw_decoration(const C2DBounds& viewport,const TGLText& writer)
{
	data->draw_decoration(viewport,writer,get_color2());
}

void TMeasure::do_select()
{
	show();
}

bool TMeasure::do_export(FILE *f)const
{
#pragma warn "export_object should return something" 	
	data->arrow_list.export_object();
	return true; 
}

void TMeasure::gl_attach()
{
	cerr << "TMeasure::gl_attach()" << endl; 
	data->arrow_list.gl_attach();
}
void TMeasure::gl_detach()
{
	data->arrow_list.gl_detach();
}
