#pragma once

#include "MotionOptimizerInterfaces.h"
#include "BSplineOpen.h"
#include "B3PApproximation.h"

class BSplineApproximator;
class CBezierApproximation;
TYPEDEF_AUTOPTR(BSplineApproximator);

class CBSplineApprTest:
		public IDrawable
{
public:
	// This structure describes the approximation parameters
	struct Params
	{
		enum DefEnum {nDefRot, nDefPos};
		Params(DefEnum nDef);
    
		// enables Newton-Raphson nonlinear step
		int bEnableNR;

		// how much the error must fall back in the first (increasing CP number) pass
		float fErrorFallback; // (0 (1..10) 1e3)

		// the precision of the optimization, regarding to the Y range
		float fPrecision; // (1 (50 .. 50000) 65536)

		// the range to which to clamp the position values when calculating required precision
		// (0..inf)
		float fValRangeClampMin, fValRangeClampMax;

		// number of Newton-raphson iterations, effective if enabled
		int nNRIters;

		// max degree of the spline
		int nDegree;

		// smoothing factor
		double fSmoothing;

		// the minimal ratio samples/knots when the NR pass is enabled
		float fMinSPKForNR;
	};


	CBSplineApprTest (const std::vector<int>& vTimes, const std::vector<Vec3d>& vPos, Params params, bool isOpen);
	CBSplineApprTest(const char* szFileName);

	void onDraw (CDC* pDC, CMotionOptimizerView* pView);

	BSplineVec3d* getSpline ()
	{
		return m_pSpline;
	}
	void Reoptimize (Params params);
	Params m_Params;
protected:

	void initApproximator (const std::vector<int>& vTimes, const std::vector<Vec3d>& vPos);
	void optimize();

	CPoint VecToPoint (const Vec3d& pt);
	Vec3d PointToVec (const CPoint& pt);

	BSplineApproximator_AutoPtr m_pApproximator;
	BSplineVec3d_AutoPtr m_pSpline;

	std::string m_sMsg;

	CB3PApproximation m_B3P;

	// the scale to multiply the time before passing to the output spline
	float m_fTimeScale;

	Vec3d m_ptMin, m_ptMax;

	bool m_isOpen; // construct an open spline?
};

TYPEDEF_AUTOPTR(CBSplineApprTest)