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

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <mia.hh>
using namespace mia; 

#include <GL/gl.h>
#include <viewit/drawable.hh>

#include <queue>

class TCounter {
	size_t crosses; 
	C3DFVector sum_speed; 
	bool counted;
	
public:
	TCounter();
	
	const C3DFVector& get_sum_speed()const;
	
	size_t get_crossings() const; 
	
	bool add_crossing(const C3DFVector& speed);
	
	C3DFVector get_avg_speed() const;
};

typedef C3DFDatafield T3DCounter; 
typedef std::list<C3DBounds> TCollector; 
typedef std::list<C3DFVector> TCriticalLocations; 

class TPixel {
	static float max_time; 
	
	int dead; 
	float remain; 	
	C3DFVector where; 	
public:	
	
	enum TPixelType {pt_unspecified,pt_forward, pt_backward};
	
	TPixel(const C3DFVector& _where);
	static void set_max_time(float _max_time);
	void set_dead_state(int dead_state);
	int get_dead_state() const;
	const C3DFVector& get_where() const; 
	
	virtual void do_move(const C3DFVector& add);
	void move(const C3DFVector& add,float timestep);
	void gl_vertex()const;
	
	virtual TPixelType get_type()const;
	
	TPixel& operator += (const C3DFVector& v);
	TPixel& operator -= (const C3DFVector& v);
protected: 
	void set_color(const C3DFVector& col);
private:	
	
};

class TSpeedPixel {
	float norm; 
	C3DFVector loc; 
public:		
	TSpeedPixel(float _norm, C3DFVector _loc):norm(_norm),loc(_loc){};
	float get_norm()const {return norm;};
	const C3DFVector& get_loc()const {return loc;};
	bool operator < (const TSpeedPixel& b)const {
		return (norm < b.norm); 
	}
};

typedef std::priority_queue<TSpeedPixel> TSpeedPixelQueue;

class TForwardPixel:public TPixel {
public:
	TForwardPixel(const C3DFVector& _where);
	virtual void do_move(const C3DFVector& add);
	virtual TPixelType get_type()const;
};

class TBackwardPixel:public TPixel {
public:
	TBackwardPixel(const C3DFVector& _where);
	virtual void do_move(const C3DFVector& add);
	virtual TPixelType get_type()const;
};

class   TPixelList: public TDrawable {
	
public:	
	typedef std::list<TPixel *> TList;
	TPixelList(const string& name);
	TPixelList(const string& name,const TColor& color); 
	TPixelList(const string& name,const TPixelList& org);
	~TPixelList();
	void clear();
	void do_gl_draw(const TCamera& c) const; 
	const TPixelList::TList& get_list() const;
	TPixelList::TList& get_list();
	void remove_dead_front_pixels();
	void remove_dead_pixels();
	//	virtual void povray_output_object(FILE *f)const{};
	//	virtual void povray_output_attributes(FILE *f)const{};	
private:
	TList *list; 
};



// inline implementations

inline void TPixel::set_dead_state(int dead_state)
{
	dead = dead_state;
}

inline int TPixel::get_dead_state() const
{
	return dead; 
}

inline const C3DFVector& TPixel::get_where() const
{
	return where; 
}


inline TPixel& TPixel::operator  += (const C3DFVector& v)
{
	where += v; 
	return *this;
}
inline TPixel& TPixel::operator  -= (const C3DFVector& v)
{
	where -= v; 
	return *this; 
}

inline void TPixel::gl_vertex()const
{
	glVertex3fv(&where.x);
}

inline const C3DFVector& TCounter::get_sum_speed() const 
{
	return sum_speed;
}
inline size_t TCounter::get_crossings() const 
{
	return crosses; 
}


inline const TPixelList::TList& TPixelList::get_list()const
{
	return *list; 
}

inline TPixelList::TList& TPixelList::get_list()
{
	return *list; 
}

#endif

