#ifndef __FLUIDSOLVERC_H__
#define __FLUIDSOLVERC_H__

#include "PajaTypes.h"
#include "Vector2C.h"
#include "rfftw.h"


// dim must be power of two!!!

class FluidSolverC
{
public:
	FluidSolverC();
	virtual ~FluidSolverC();

	void				init( PajaTypes::int32 i32Dim );
	void				reset();
	void				solve( PajaTypes::float32 f32DT );
	void				drag( PajaTypes::float32 f32X, PajaTypes::float32 f32Y, PajaTypes::Vector2C rForce, PajaTypes::float32 f32Matter );
	void				push( PajaTypes::float32 f32X, PajaTypes::float32 f32Y, PajaTypes::Vector2C rForce, PajaTypes::float32 f32Amount );

	void				smooth();

	void				add_force( PajaTypes::uint32 ui32X, PajaTypes::uint32 ui32Y, PajaTypes::Vector2C rForce );

	PajaTypes::int32	get_dimension() const;
	fftw_real*			get_density_ptr();
	fftw_real*			get_smooth_density_ptr();
	fftw_real*			get_velocity_u_ptr();
	fftw_real*			get_velocity_v_ptr();

protected:

	void	stable_solve( PajaTypes::int32 n, fftw_real* u, fftw_real* v, fftw_real* u0, fftw_real* v0, fftw_real visc, fftw_real dt );
	void	diffuse_matter( PajaTypes::int32 n, fftw_real* u, fftw_real* v, fftw_real* rho, fftw_real* rho0, fftw_real dt );
	void	set_forces( void );

	PajaTypes::float32	m_f32Time;
	PajaTypes::int32	m_i32Dim;

	fftw_real*			m_pU;
	fftw_real*			m_pV;
	fftw_real*			m_pU0;
	fftw_real*			m_pV0;
	fftw_real*			m_pRho;		// Smoke density
	fftw_real*			m_pRhoSmooth;		// Smoke density
	fftw_real*			m_pRho0;
	fftw_real*			m_pU_U0;	// User-induced forces
	fftw_real*			m_pU_V0;

	static bool			m_bInitialised;
	static rfftwnd_plan	m_rPlanRC, m_rPlanCR;
};


#endif //__FLUIDSOLVERC_H__