#include <iostream>
using namespace std;

#include "Parameters.hpp"


Parameters::Parameters(unsigned int num_parameters, float default_val):
        num_parameters(num_parameters) {
    begin = new (nothrow) Vector(num_parameters, default_val);
    eind = new (nothrow) Vector(num_parameters, default_val);
    interpolated = new (nothrow) Vector(num_parameters, default_val);
    // *interpolated = *begin

    check_pointers();

#ifdef HARDDEBUG
    cout << "New Parameters with one default val:" << endl << *this << endl;
#endif
}

/*Parameters::Parameters(unsigned int num_parameters, float default_val1, float default_val2):
        num_parameters(num_parameters) {
    begin = new (nothrow) Vector(num_parameters, default_val1);
    eind = new (nothrow) Vector(num_parameters, default_val2);
    interpolated = new (nothrow) Vector(num_parameters, default_val1);
    // *interpolated = *begin

    check_pointers();

#ifdef HARDDEBUG
    cout << "New Parameters with two default vals:" << endl << *this << endl;
#endif
}*/

Parameters::~Parameters() {
    delete begin;
    delete eind;
    delete interpolated;

#ifdef HARDDEBUG
    cout << "Parameters deleted" << endl;
#endif
}

void Parameters::check_pointers() {
    assert(begin != NULL);
    assert(eind != NULL);
    assert(interpolated != NULL);
}

void Parameters::set(unsigned int parameter, float val1, float val2) {
    assert(parameter < num_parameters);

    begin->coordinates[parameter] = val1;
    eind->coordinates[parameter] = val2;
    interpolated->coordinates[parameter] = val1;

#ifdef HARDDEBUG
    cout << "Parameter " << parameter << " set to: " << val1 << " - " << val2 << endl;
#endif
}

void Parameters::set(unsigned int parameter, float val) {
    assert(parameter < num_parameters);

    begin->coordinates[parameter] = val;
    eind->coordinates[parameter] = val;
    interpolated->coordinates[parameter] = val;

#ifdef HARDDEBUG
    cout << "Parameter " << parameter << " set to: " << val << endl;
#endif
}

float Parameters::get(unsigned int parameter) {
    assert(parameter < num_parameters);

#ifdef HARDDEBUG
    cout << "Asked for parameter " << parameter << " with value:" << interpolated->coordinates[parameter] << endl;
#endif

    return interpolated->coordinates[parameter];

}

void Parameters::interpolate(float time) {
    /*
        Dit is mogelijk met vector rekenen:
        (*interpolated) = (*begin) * ( 1.0 - time ) + (*eind) * time;
        Maar we doen het per element, zodat we simpelere code hebben,
        geen vectoren hoeven te returnen en makkelijker kunnen optimaliseren
    */
    const float invtime = 1.0 - time;
    for ( unsigned int i = 0; i < num_parameters; i++ ) {
        interpolated->coordinates[i] = invtime * begin->coordinates[i] + time * eind->coordinates[i];
    }

#ifdef HARDDEBUG
    cout << "interpolate() result" << endl << *interpolated << endl;
#endif
}

ostream& operator<<(ostream& os, const Parameters& param) {
    os << param.num_parameters << endl;
    os << "Begin:" << endl << *param.begin << endl;
    os << "Eind:" << endl << *param.eind << endl;
    os << "Interpolated:" << endl << *param.interpolated << endl;
    os <<endl;
    return os;
}