#ifndef PROJECTOR_HPP
#define PROJECTOR_HPP

#include "Logger.hpp"
#include <algorithm>

#include "stfu/stf.hpp"
#include "Canvas.hpp"

class Projector {
public:
	// SHOULD NOT BE HERE
	Canvas* canvas;

	Projector(unsigned int inputDimension, unsigned int outputDimension) :
		canvas(0), projector(0), projectedPoint(0),
		inputDimension(inputDimension), outputDimension(outputDimension),
		ready(true) {
		try {
			allocate();
		} catch(std::exception& e) {
			LogError("Couldn't construct Projector: %s\n", e.what());
			deallocate();
		}
		std::fill_n(projectedPoint, outputDimension, 0.0);
	}

	virtual ~Projector() {
		deallocate();
	}

	void plot(const double* point) {
		project(point);

		if(ready) {
			if(canvas != NULL) {
				canvas->plot(projectedPoint);
			}

			if(projector != NULL) {
				projector->plot(projectedPoint);
			}
		}
	}

	static Projector* createProjector(stfu::node& projector, unsigned int input_dimension);

protected:
	Projector* projector;

	double* projectedPoint;

	unsigned int inputDimension;
	unsigned int outputDimension;

	bool ready;

	virtual void project(const double* point) = 0;

private:
	void allocate() {
		projectedPoint = new double[outputDimension];
	}

	void deallocate() {
		delete[] projectedPoint;
		projectedPoint = NULL;
	}
};

#endif // PROJECTOR_HPP