#ifndef WIDGETS_GRAPHPLOTTER_INTERPOLATOR_H
#define WIDGETS_GRAPHPLOTTER_INTERPOLATOR_H

#include "Common.h"
#include "Vector2D.h"

#include <map>


// -- TDE NAMESPACE ----------------------------------------------------

namespace TDE {

// -- Widgets NAMESPACE ------------------------------------------------

namespace Widgets {

namespace Plot {


class Interpolator;

typedef SHARED_PTR<Interpolator> InterpolatorPtr;

// see http://stackoverflow.com/a/1730798
class InterpolatorParameters
{
public:
	InterpolatorParameters() {}
	InterpolatorParameters(const std::string& name, double value) { m_params[name] = value; }
	InterpolatorParameters(const InterpolatorParameters& other) : m_params(other.m_params) {}
	virtual ~InterpolatorParameters() {}

	InterpolatorParameters& operator()(const std::string& name, double value)
	{
		m_params[name] = value;
		return *this;
	}

	InterpolatorParameters& operator= (const InterpolatorParameters& other)
	{
		m_params = other.m_params;
		return *this;
	}

	operator std::map<std::string, double>()
	{
		return m_params;
	}

	operator InterpolatorParameters()
	{
		return InterpolatorParameters(*this);
	}

	double get(const std::string& name) const { return m_params.at(name); }
	double get(const std::string& name, double defaultValue) const
	{
		return (m_params.count(name) > 0) ? m_params.at(name) : defaultValue;
	}
	InterpolatorParameters& set(const std::string& name, double value) { m_params[name] = value; return *this; }
	bool has(const std::string& name) const { return (m_params.count(name) != 0) ? true : false; }

	double operator[] (const std::string& name)  { return get(name); }

private:
	std::map<std::string, double> m_params;
};

class Interpolator
{
public:
	Interpolator();
	Interpolator(const InterpolatorParameters& params);
	virtual ~Interpolator() = 0;

	virtual double compute(double x) const = 0;
	virtual double operator()(double x) const 	{ return compute(x); }

	Range range() const 				{ return m_range; }

	InterpolatorParameters& parameters() { return m_parameters; }
	double getParameter(const std::string& name) const { return m_parameters.get(name); }
	double getParameter(const std::string& name, double defaultValue) const { return m_parameters.get(name, defaultValue); }
	InterpolatorParameters& setParameter(const std::string& name, double value) { return m_parameters.set(name, value); }
	double hasParameter(const std::string& name) const { return m_parameters.has(name); }

protected:
	Range m_range;
	InterpolatorParameters m_parameters;
};


} /* end of namespace Plot */

} /* end of namespace Widgets */

} /* end of namespace TDE */

#endif /* WIDGETS_GRAPHPLOTTER_INTERPOLATOR_H */
