#pragma once

#include "volumeshop.h"

#include <map>
#include <vector>
#include "Color.h"

template <class OrdinateType, class AbscissaType>
class Function1D
{
public:

	Function1D(void)
	{
	};

	virtual ~Function1D(void)
	{
	};

	void Set(const OrdinateType & tOrdinateValue, const AbscissaType & tAbscissaValue)
	{
		m_mapValues[tOrdinateValue] = tAbscissaValue;
	};

	const AbscissaType & Get(const OrdinateType & tOrdinateValue) const
	{
		std::map<OrdinateType, AbscissaType>::const_iterator i = m_mapValues.find(tOrdinateValue);
		return (*i).second;
	};

	const unsigned int GetCount() const
	{
		return m_mapValues.size();
	};

	const AbscissaType * GetLookupTable() const
	{
		return &m_vecValues.front();
	};

	virtual void update(const unsigned int uCount)
	{
		if (m_mapValues.size() > 1)
		{
			m_vecValues.resize(uCount);
			
			std::map<OrdinateType,AbscissaType>::iterator i;
			std::map<OrdinateType,AbscissaType>::iterator j;

			for (i = m_mapValues.begin(); i != m_mapValues.end();)
			{
				j = i;
				j++;

				if (j != m_mapValues.end())
				{
					const OrdinateType &tStartCoordinate = (*i).first*float(uCount-1);
					const OrdinateType &tEndCoordinate = (*j).first*float(uCount-1);

					const AbscissaType &tStartValue = (*i).second;
					const AbscissaType &tEndValue = (*j).second;

					const float fD = 1.0f / (tEndCoordinate - tStartCoordinate);
					float fT = 0.0f;

					for (OrdinateType tCoordinate = tStartCoordinate; tCoordinate < tEndCoordinate; tCoordinate++)
					{
						const AbscissaType tValue = tStartValue * (1.0f - fT) + tEndValue * fT;
						m_vecValues[unsigned int(tCoordinate)] = tValue;
						fT += fD;
					}

					m_vecValues[unsigned int(tEndCoordinate)] = tEndValue;
				}

				i = j;

			}
		}
	};

protected:

	std::map<OrdinateType, AbscissaType> m_mapValues;
	std::vector<AbscissaType> m_vecValues;

};
