////////////////////////////////////////////
//
// A C++ interface to gnuplot. 
//
// This is a direct translation from the C interface
// written by N. Devillard (which is available from
// http://ndevilla.free.fr/gnuplot/).
//
// As in the C interface this uses pipes and so wont
// run on a system that does'nt have POSIX pipe 
// support
//
// Rajarshi Guha
// <rajarshi@presidency.com>
//
// 07/03/03
//
// 26/01/04 - Gnuplot::cmd() was rewritten to accept a
// char* rather than a std::string, thus avoiding the
// va_start warning at compile time
// /////////////////////////////////////////

#ifndef _GNUPLOT_PIPES_H_
#define _GNUPLOT_PIPES_H_

#include <stdarg.h>
#ifndef WIN32
#include <unistd.h>
#endif

#include <cstdlib>
#include <cstdio>
#include <cstring>

#include <string>
#include <iostream>
#include <fstream>
#include <sstream>
#include <list>
#include <map>
#include <vector>
#include <stdexcept>

#define GP_MAX_TMP_FILES    64
#define GP_TMP_NAME_SIZE    512
#define GP_CMD_SIZE         1024
#define GP_TITLE_SIZE       80

namespace OBJREC
{

class GnuplotException: public std::runtime_error
{
public:
	GnuplotException(const std::string &msg) :
		std::runtime_error(msg)
	{
	}
};

class Gnuplot
{
private:
	FILE *gnucmd;
	std::string pstyle;
	std::vector<std::string> to_delete;
	int nplots;
	bool get_program_path(const std::string);
	bool valid;
public:
	Gnuplot();

	// set a style during construction
	Gnuplot(const std::string &);

	// The equivilant of gnuplot_plot_once, the two forms
	// allow you to plot either (x,y) pairs or just a single
	// vector at one go
	Gnuplot(const std::string &, // title
			const std::string &, // style
			const std::string &, // xlabel
			const std::string &, // ylabel
			std::vector<double> , std::vector<double> );

	Gnuplot(const std::string &, //title
			const std::string &, //style
			const std::string &, //xlabel
			const std::string &, //ylabel
			std::vector<double> );

	~Gnuplot();
	void checkSystemVariablesOpenGnuplotCommand();

	// send a command to gnuplot
	void cmd(const char*, ...);

	// set line style
	void set_style(const std::string &);
	// set name of eps file to plot to
	void setFileOutput(const std::string &terminal, const std::string &filename);
	// set y and x axis labels
	void set_ylabel(const std::string &);
	void set_xlabel(const std::string &);
	void set_zlabel(const std::string &);

	// set axis - ranges
	void set_xrange(const int iFrom, const int iTo);
	void set_yrange(const int iFrom, const int iTo);
	void set_zrange(const int iFrom, const int iTo);

	// set palette range
	void set_cbrange(const int iFrom, const int iTo);

	// plot a single vector
	void plot_x(std::vector<double> , const std::string & // title
			);

	// plot x,y pairs
	void plot_xy(std::vector<double> , std::vector<double> , const std::string & // title
			);

	// plot x,y pairs
	void plot_xy ( std::map<double, double> , const std::string & // title
			);

	// plot an equation of the form: y = ax + b
	// You supply a and b
	void plot_slope(double, // a
			double, // b
			const std::string & // title
			);

	// plot an equation supplied as a string
	void plot_equation(const std::string &, // equation
			const std::string & // title
			);

	// if multiple plots are present it will clear the plot area
	void reset_plot(void);

	bool is_valid(void);

	void plot_xyz(std::vector<double> , std::vector<double> , std::vector<double> ,
			const std::string &);

	void plot_image(unsigned char * ucPicBuf, int iWidth, int iHeight,
			const std::string &title);

};

} // namespace

#endif
