#include "AbstractionModule.h"
#include "abstraction_interface.h"

#include <stdio.h>


void AbstractionModule :: initialize_abstraction(Lookuptable* lut, unsigned int abstraction_method) {
	this->abstraction_method = abstraction_method;

	num_of_lookuptables = 0;

	for(unsigned int lut_ix=0; lut_ix<MAX_NUM_OF_LOOKUPTABLES; lut_ix++) {
		flag_lookuptable_exist[lut_ix] = false;
	}
		
	if(lut != NULL) {
		list_lookuptables[num_of_lookuptables] = lut;
		flag_lookuptable_exist[num_of_lookuptables] = true;
		lookuptable_to_use = num_of_lookuptables;
		num_of_lookuptables++;
	}
}

AbstractionModule :: AbstractionModule(Lookuptable* lut, unsigned int abstraction_method) {
	set_name(NO_NAME);
	initialize_abstraction(lut, abstraction_method);
}

AbstractionModule :: AbstractionModule(char* name, Lookuptable* lut, unsigned int abstraction_method) {
	set_name(name);
	initialize_abstraction(lut, abstraction_method);
}

bool AbstractionModule :: set_abstraction_method(unsigned int abstraction_strategy) {
	if(abstraction_strategy < NUM_OF_ABSTRACTIONS) {
		this->abstraction_method = abstraction_strategy;
		return true;
	}
	return false;
}

unsigned int AbstractionModule :: get_abstraction_method() {
	return abstraction_method;
}

bool AbstractionModule :: add_lookuptable(Lookuptable* lut) {
	if(num_of_lookuptables < MAX_NUM_OF_LOOKUPTABLES && lut != NULL) {
		flag_lookuptable_exist[num_of_lookuptables] = true;
		num_of_lookuptables++;
		return true;
	}
	return false;
}

bool AbstractionModule :: get_flag_lookuptable_exist(unsigned int position) {
	if(position < num_of_lookuptables) {
		return flag_lookuptable_exist[position];
	}
	return false;
}

Lookuptable* AbstractionModule :: get_lookuptable(unsigned int position) {
	if(position < num_of_lookuptables) {
		return list_lookuptables[position];
	}
	return NULL;
}

/*
bool Abstraction :: connect_with_lookuptable(unsigned int position, Lookuptable* lut) {
	if(position < num_of_sensors) {
		list_lookuptables_float[position] = lut;
		return true;
	}
	return false;
}

void Abstraction :: set_num_of_slaveagents(unsigned int num_of_slaveagents) {
	this->num_of_slaveagents = num_of_slaveagents;
}

unsigned int Abstraction :: get_num_of_slaveagents() {
	return num_of_slaveagents;
}

void Abstraction :: set_num_of_sensors(unsigned int num_of_sensors) {
	this->num_of_sensors = num_of_sensors;
}

unsigned int Abstraction :: get_num_of_sensors() {
	return num_of_sensors;
}

bool Abstraction :: set_input_parameter(unsigned int position, int input_parameter) {
	if(position < MAX_NUM_OF_INPUT_VALUES) {
		flag_input_data_int_is_in_use[position] = true;
		input_data_int[position] = input_parameter;
		return true;
	}
	return false;
}

bool Abstraction :: set_input_parameter(unsigned int position, float input_parameter) {
	if(position < MAX_NUM_OF_INPUT_VALUES) {
		flag_input_data_float_is_in_use[position] = true;
		input_data_float[position] = input_parameter;
		return true;
	}
	return false;
}

bool Abstraction :: get_input_parameter(unsigned int position, int* input_parameter) {
	if(position < MAX_NUM_OF_INPUT_VALUES) {
		if(flag_input_data_int_is_in_use[position]) {
			*input_parameter = input_data_int[position];
			return true;
		}
	}
	return false;
}
bool Abstraction :: get_input_parameter(unsigned int position, float* input_parameter) {
	if(position < MAX_NUM_OF_INPUT_VALUES) {
		if(flag_input_data_float_is_in_use[position]) {
			*input_parameter = input_data_float[position];
			return true;
		}
	}
	return false;
}*/

bool AbstractionModule :: abstract(float input, int* output) {
	
	switch(abstraction_method) {

		case ABSTRACTION_METHOD_NOT_SPECIFIED: return false;
		case ABSTRACTION_LOOKUPTABLE: return abstract_via_lookuptable(input, output); break;
		 
		default:return false; break;//TODO: interface

		//default: return abstract_interface(abstraction_method, num_of_slaveagents, flag_input_data_int_is_in_use, input_data_int, num_of_sensors, flag_input_data_float_is_in_use, input_data_float); break;
	}
	
	/*
	if(abstraction_method == ABSTRACTION_METHOD_NOT_SPECIFIED)
		return false;

	return abstract_data(abstraction_method, num_of_mounted_slaveagents, flag_input_data_int_is_in_use, input_data_int, num_of_mounted_sensors, flag_input_data_float_is_in_use, input_data_float);
	*/


}

bool AbstractionModule :: abstract_via_lookuptable(float input, int* output) {

	if(list_lookuptables[lookuptable_to_use]->get_lookuptable_is_correct_and_active()) {
		*output = list_lookuptables[lookuptable_to_use]->get_score(input);
		return true;
	}

	return false; //dummy
}



/*
bool Abstraction :: add_score_to_input_data_lookuptable(unsigned int position, float lower_boundary, float upper_boundary, int score, bool flag_lower_boundary_exist, bool flag_upper_boundary_exist, bool flag_lower_boundary_included, bool flag_upper_boundary_included) {

	if(flag_input_data_range_is_activated[position] == false) {

		bool flag_found_empty_position = false;

		for(unsigned int pos=0; pos<MAX_NUM_OF_INPUT_VALUES; pos++) {




		}



	}

	return false;
}
*/








bool AbstractionModule :: abstract_via_lookuptables_and_condition_variable() {


	return true;
}