/*! \file ThinningMethod.h
    \brief Implementation of the Template class ThinningMethod.
    
    Magics Team - ECMWF 2010
    
    Started: Thu 28-Oct-2010
    
    Changes:
    
*/



#include "ThinningMethod.h"
#include "Data.h"

using namespace magics;

ThinningMethod::ThinningMethod() 
{
}


ThinningMethod::~ThinningMethod() 
{
}

/*!
 Class information are given to the output-stream.
*/		
void ThinningMethod::print(ostream& out)  const
{
	out << "ThinningMethod[";
	out << "]";
}

AutomaticThinningMethod::AutomaticThinningMethod() 
{
}


void ThinningMethod::operator()(Data<UserPoint>&, const Transformation&, const std::set<string>&, CustomisedPointsList&)
{
}
void ThinningMethod::operator()(Data<GeoPoint>&, const Transformation&, const std::set<string>&, CustomisedPointsList&)
{
	
}

void BasicThinningMethod::operator()(Data<UserPoint>&data,
		const Transformation& transformation,
		const std::set<string>& request, CustomisedPointsList& points)
{
	try {
		data.customisedPoints(*this, transformation, request, points);
	}

	catch ( ...) {
		data.customisedPoints(transformation, request, points);
	}
}
void BasicThinningMethod::operator()(Data<GeoPoint>& data, 
		const Transformation& transformation, 
		const std::set<string>& request, CustomisedPointsList& points)
{
	try {
				data.customisedPoints(*this, transformation, request, points);
			}
			
			catch ( ...) {
				data.customisedPoints(transformation, request, points);
			}
}

void AutomaticThinningMethod::operator()(Data<UserPoint>& data,
		const Transformation& transformation, const std::set<string>& request, CustomisedPointsList& points)
{

	try {
				data.customisedPoints(*this, transformation, request, points);
			}

			catch ( ...) {
				data.customisedPoints(transformation, request, points);
			}
}
void AutomaticThinningMethod::operator()(Data<GeoPoint>& data, 
			const Transformation& transformation, const std::set<string>& request, CustomisedPointsList& points)
{

	
	try {
				data.customisedPoints(*this, transformation, request, points);
			}
			
			catch ( ...) {
				data.customisedPoints(transformation, request, points);
			}
	
}
AutomaticThinningMethod::~AutomaticThinningMethod() 
{
}

void AutomaticThinningMethod::set(const ThinningMethodUI& ui) 
{
	nbPoints_ = ui.nbPoints_;
	rawOnly_ = ui.rawOnly_; // If true, do not thin .. only show raw data if resolution allows it! 
}


BasicThinningMethod::BasicThinningMethod() 
{
}


BasicThinningMethod::~BasicThinningMethod() 
{
}

void BasicThinningMethod::set(const ThinningMethodUI& ui) 
{
	factor_ = ui.factor_;
}

static SimpleObjectMaker<AutomaticThinningMethod, ThinningMethod> automatic("automatic");
static SimpleObjectMaker<BasicThinningMethod, BasicThinningMethod> basic("basic");
static SimpleObjectMaker<BasicThinningMethod, BasicThinningMethod> data("data");

/*
const Transformation& transformation = parent.transformation();
try {
	MatrixHandler<P>& inx = data.xComponent();
	MatrixHandler<P>& iny = data.yComponent();

	vector<GeoPoint> thinx;
	vector<GeoPoint> thiny;
	
 int xfactor = this->thinning_factor_;
	if ( magCompare(this->thinning_method_, "automatic" ) ) {
		// We need to recalcalate the thinning ...			
		double width = parent.transformation().getMaxX() - parent.transformation().getMinX();
		this->thinning_factor_ = (width/this->thinning_factor_) / inx .XResolution();
		xfactor = (int) ceil((float)  this->thinning_factor_);
		 
		MagLog::dev() << " Thinning factor->" << this->thinning_factor_ << endl;
		
	}
	this->thinning_factor_ = xfactor;
	(*this->type_).prepare(parent, xfactor*inx .XResolution());

	transformation.thin(inx, this->thinning_factor_, this->thinning_factor_, thinx);
	transformation.thin(iny, this->thinning_factor_, this->thinning_factor_, thiny);

	typename vector<P>::const_iterator x = thinx.begin();
	typename vector<P>::const_iterator y = thiny.begin();

	while ( x != thinx.end() && y != thiny.end() )
	{
		
		if ( x->value() != inx.missing() &&  y->value() != iny.missing() ) {
		    pair<double, double> component = make_pair( x->value(), y->value());
		    transformation.reprojectComponents(*x, component);
			(*this->type_)(*x, transformation(*x), component.first,  component.second, 0);
		}
		// Here we could check that the lat/lon of the x and y coordinates are the same...
		x++;
		y++;
	} 
}
catch ( MagException& e) 
{
*/

