#include <string.h>
#include <time.h>

#include <float.h>

#include "configuration.h"

#include "MathsResolver.h"

#include "problema.h"
#include "method.h"
#include "result.h"

#include "logger.h"
#include "utilities.h"

static
	void fillResult(
			Result   *r,
			Problema *pb,
			Method   *m)
{
	if( m->_result_loaded )
	{
		r->_result_complexity = m->_last_complexity;
		r->_problem_dimension = pb->_dimension;
		if( m->_last_result )
		{
			r->_result_vector  = (double *)malloc(pb->_dimension * sizeof(double));
			memcpy(r->_result_vector,m->_last_result,pb->_dimension*sizeof(double));
			r->_result_value = pb->compute(pb,r->_result_vector,r->_problem_dimension)[0];
		}
		else
		{
			r->_result_vector = NULL;
			r->_result_value  = DBL_MAX;
		}

		loadMethodParameters(&(r->_initialParameters),m->parameters);

		r->_data_loaded =
				INITIAL_VECTOR_LOADED
				| INITIAL_PARAMETERS_LOADED
				| RESULT_COMPLEXITY_LOADED
				| RESULT_VECTOR_LOADED
				| RESULT_VALUE_LOADED;

		if ( pb->_solution && r->_result_error > 0)
		{
			r->_result_error      = m->_last_absolute_error;
			r->_data_loaded      |= RESULT_ERROR_LOADED;
		}

		m->clearResult(m);
	}
	else
	{
		logMessage(SEVERE,"result filling","some data weren't load after the method resolution");
	}
}

Result* resolve(
	Problema         *pb,
	Method           *m,
	double           *initial_vector,
	MethodParameters  args
	)
{
	Result *result = NULL;

	logMessage(DEBUG2,"result creation","creating result skeletion");
	result = createResult(0,pb->getId(pb),m->getId(m));
	//TODO Replace asap
//	result = DAOcreateResult(result);

	result->_initial_vector = (double *)malloc(pb->_dimension * sizeof(double));
	memcpy(result->_initial_vector,initial_vector,pb->_dimension * sizeof(double));

	logMessage(DEBUG2,"launch resolve method",m->_name);

	m->_method_function(
		pb,
		m,
		initial_vector,
        args);

	logMessage(DEBUG2,"after method","fill result");

	fillResult(result,pb,m);

	if(!result->_data_loaded)
	{
		logMessage(SEVERE,"result ready","result badly built");
		return NULL;
	}

	time_t now = time(NULL);
	localtime_r(&now,&(result->run_date));

	logMessage(DEBUG2,"result built","Done.");

	logMessage(DEBUG2,"exiting method","resolve");

	return result;
}
