#include "ConfidenceModule.h"
#include "HistoryModule.h"

#include <stdio.h>

//TODO: at the moment are only positive rates_of_changes allowed!!
void ConfidenceModule :: initialize_confidence_validator(float lower_bound, bool flag_lower_bound_exist, float upper_bound, bool flag_upper_bound_exist, float rates_of_change, bool flag_rates_of_change_exist) {
	//plausibility
	if(lower_bound <= upper_bound) {
		this->lower_bound = lower_bound;
		this->upper_bound = upper_bound;
		this->flag_lower_bound_exist = flag_lower_bound_exist;
		this->flag_upper_bound_exist = flag_upper_bound_exist;
	}
	else {
		this->lower_bound = upper_bound;
		this->upper_bound = lower_bound;
		this->flag_lower_bound_exist = flag_upper_bound_exist;
		this->flag_upper_bound_exist = flag_lower_bound_exist;
	}
	
	//consistency
	this->rates_of_change = rates_of_change;
	this->flag_rates_of_change_exist = flag_rates_of_change_exist;
	flag_value_got_inconsistence = false;

	//TODO: Changes of Other Sensors (e.g. Environment Temperature Sensor)
}

ConfidenceModule :: ConfidenceModule(float lower_bound, bool flag_lower_bound_exist, float upper_bound, bool flag_upper_bound_exist, float rates_of_change, bool flag_rates_of_change_exist) {
	set_name(NO_NAME);
	initialize_confidence_validator(lower_bound, flag_lower_bound_exist, upper_bound, flag_upper_bound_exist, rates_of_change, flag_rates_of_change_exist);
}


ConfidenceModule :: ConfidenceModule(char* name, float lower_bound, bool flag_lower_bound_exist, float upper_bound, bool flag_upper_bound_exist, float rates_of_change, bool flag_rates_of_change_exist) {
	set_name(name);
	initialize_confidence_validator(lower_bound, flag_lower_bound_exist, upper_bound, flag_upper_bound_exist, rates_of_change, flag_rates_of_change_exist);
}

bool ConfidenceModule :: validate_confidence(float input/*, HistoryModule* historyModule*/) {

	bool flag_confidence = true;

	

	//bounds
	if(flag_lower_bound_exist && input < lower_bound) {
		flag_confidence = false;
		//printf("lb\ninput = %f\n", input);
	}

	if(flag_upper_bound_exist && input > upper_bound) {
		flag_confidence = false;
		//printf("ub\n");
	}

	//rates_of_change
	float trend_abs = .0;
	//TODO: time_unites and time_base should be configurable and saved for the object
	//unsigned int time_units = 2;
	bool got_trend = false; //XXX historyModule->get_history_trend_absolutely(&trend_abs, time_units, TB_SECONDS);

	if(got_trend) {
		if(trend_abs > rates_of_change) {
			flag_confidence = false;
			//printf("trend\n");

			//VERSUCH
			if(flag_value_got_inconsistence == false) {
				//printf("setze flag\n");
				flag_value_got_inconsistence = true;
				value_before_value_got_inconsistence = 0; //XXX historyModule->get_value_ago(time_units);
			}
		}
	}
	else {
		//printf("no trend\n");
	}

	if(flag_value_got_inconsistence) {

		//TODO: nicht hardcoded
		float seconds = 20;

		//printf("tradition\n");

		if(input == value_before_value_got_inconsistence) {
			flag_value_got_inconsistence = false;
		}
		else if(input < value_before_value_got_inconsistence) {
			if(input >= value_before_value_got_inconsistence-rates_of_change*seconds) {
				flag_value_got_inconsistence = false;
			}
			else {
				flag_confidence = false;
			}
		}
		else if(input > value_before_value_got_inconsistence) {
			if(input <= value_before_value_got_inconsistence+rates_of_change*seconds) {
				flag_value_got_inconsistence = false;
			}
			else {
				flag_confidence = false;
			}
		}
		else {
			flag_confidence = false;
		}
	}


	confidence = flag_confidence;
	return confidence;
}

bool ConfidenceModule :: get_confidence() {
	return confidence;
}

void ConfidenceModule :: set_lower_bound(float lower_bound) {
	this->lower_bound = lower_bound;
} 

float ConfidenceModule :: get_lower_bound() {
	return lower_bound;
} 

void ConfidenceModule :: set_flag_lower_bound_exist(bool flag) {
	this->flag_lower_bound_exist = flag;
} 

bool ConfidenceModule :: get_flag_lower_bound_exist() {
	return flag_lower_bound_exist;
} 

void ConfidenceModule :: set_upper_bound(float upper_bound) {
	this->upper_bound = upper_bound;
} 

float ConfidenceModule :: get_upper_bound() {
	return upper_bound;
} 

void ConfidenceModule :: set_flag_upper_bound_exist(bool flag) {
	this->flag_upper_bound_exist = flag;
} 

bool ConfidenceModule :: get_flag_upper_bound_exist() {
	return flag_upper_bound_exist;
} 

void ConfidenceModule :: set_rates_of_change(float rates) {
	this->rates_of_change = rates;
} 

float ConfidenceModule :: get_rates_of_change() {
	return rates_of_change;
} 

void ConfidenceModule :: set_flag_rates_of_change_exist(bool flag) {
	this->flag_rates_of_change_exist = flag;
} 

bool ConfidenceModule :: get_flag_rates_of_change_exist() {
	return flag_rates_of_change_exist;
} 
