#include "Testbench.h"

#include "printError.h"
#include <stdio.h>

#define MAXNUMOF_REGISTEREDCAGENTS 1000
#define MAXNUMOF_REGISTEREDCHANNELS 1000
#define MAXNUMOF_REGISTEREDSENSORS 1000

using namespace std;

void Testbench :: init_testbench() {
	maxNumOf_registeredAgents = MAXNUMOF_REGISTEREDCAGENTS;
	maxNumOf_registeredChannels = MAXNUMOF_REGISTEREDCHANNELS;
	maxNumOf_registeredSensors = MAXNUMOF_REGISTEREDSENSORS;
}

Testbench :: Testbench() {
	set_name(NO_NAME);
}

Testbench :: Testbench(const char* name) {
	set_name(name);
}

bool Testbench :: register_agent(Agent* agent) {
	AgentSlotOfTestbench* agentSlot = new AgentSlotOfTestbench();
	if(agentSlot != NULL) {
		if(agentSlot->set_agent(agent)) {
			try {
				if(vector_registeredAgents.size() < maxNumOf_registeredAgents) {
					vector_registeredAgents.push_back(agentSlot);
				}
				else {
					printError("Max number of registered agents is already reached!");
					return false;
				}
			}
			catch(bad_alloc& error) {
				printError("bad_alloc caught: ", error.what());
				return false;
			}
			return true;
		}
		else {
			printError("Agent is not set!");
			vector_registeredAgents.pop_back(); //TODO: check if it is right?!?!
			return false;
		}
	}
	else {
		printError("Couldn't create AgentSlot!");
		return false;
	}
}

bool Testbench :: register_sensor(Sensor* sensor) {
	SensorSlotOfTestbench* sensorSlot = new SensorSlotOfTestbench();
	if(sensorSlot != NULL) {
		if(sensorSlot->set_sensor(sensor)) {
			try {
				if(vector_registeredSensors.size() < maxNumOf_registeredSensors) {
					vector_registeredSensors.push_back(sensorSlot);
				}
				else {
					printError("Max number of registered sensors is already reached!");
					return false;
				}
			}
			catch(bad_alloc& error) {
				printError("bad_alloc caught: ", error.what());
				return false;
			}
			return true;
		}
		else {
			printError("Input port is no set!");
			vector_registeredSensors.pop_back(); //TODO: check if it is right?!?!
			return false;
		}
	}
	else {
		printError("Couldn't create SensorSlot!");
		return false;
	}
}

SensorSlotOfTestbench* Testbench :: get_sensorSlotAddressOfTestbench(Sensor* sensor) {
	for(auto &sensorSlot : vector_registeredSensors) {
		if(sensorSlot->get_sensor() == sensor) {
			return sensorSlot;
		}
	}
	return NULL;
}


bool Testbench :: register_channel(Channel* channel) {
	ChannelSlotOfTestbench* channelSlot = new ChannelSlotOfTestbench();
	if(channelSlot != NULL) {
		if(channelSlot->set_channel(channel)) {
			try {
				if(vector_registeredChannels.size() < maxNumOf_registeredChannels) {
					vector_registeredChannels.push_back(channelSlot);
				}
				else {
					printError("Max number of registered channels is already reached!");
					return false;
				}
			}
			catch(bad_alloc& error) {
				printError("bad_alloc caught: ", error.what());
				return false;
			}
			return true;
		}
		else {
			printError("Channel is not set!");
			vector_registeredChannels.pop_back(); //TODO: check if it is right?!?!
			return false;
		}
	}
	else {
		printError("Couldn't create ChannelSlot!");
		return false;
	}
}

void Testbench :: simulate(unsigned int rounds) {
	for(unsigned int sec=1; sec<=rounds; sec++) {
		
		printf("cycle %u\n", sec);

		//update sensor values
		for(auto &sensorSlot : vector_registeredSensors) {
			Sensor *sensor = sensorSlot->get_sensor();
			if(sensor != NULL) {
				CSVreaderModule *csvReader = sensorSlot->get_csvReaderModule();
				if(csvReader != NULL) {
					float inputValue;
					if(csvReader->get_next_value(&inputValue)) {
						sensor->set_sensorValue(inputValue);
					}
				}
			}
		}

		//trigger sensors
		for(auto &sensorSlot : vector_registeredSensors) {
			Sensor *sensor = sensorSlot->get_sensor();
			if(sensor != NULL) {
				sensor->trigger();
			}
		}

		//trigger channels
		for(auto &channelSlot : vector_registeredChannels) {
			Channel *channel = channelSlot->get_channel();
			if(channel != NULL) {
				channel->trigger();
			}
		}

		//trigger agents
		for(auto &agentSlot : vector_registeredAgents) {
			Agent *agent = agentSlot->get_agent();
			if(agent != NULL) {
				agent->trigger();
			}
		}
		getchar();
	}
}





/*
Testbench :: Testbench() {
	num_of_registered_agents = 0;
	num_of_registered_sensors = 0;
	num_of_registered_channels = 0;

	this->id = num_of_units;
	num_of_units++;
	this->set_name(NO_NAME);

	//csv
	flag_csv_reader_exist = false;
	flag_csv_writer_exist = false;
}

Testbench :: Testbench(char* name) {
	num_of_registered_agents = 0;
	num_of_registered_sensors = 0;
	num_of_registered_channels = 0;

	this->id = num_of_units;
	num_of_units++;
	this->set_name(name);

	//csv
	flag_csv_reader_exist = false;
	flag_csv_writer_exist = false;
}

void Testbench :: simulate() {

	if(flag_csv_writer_exist) {

		csv_writer->write_field("second");
		csv_writer->make_new_field();

		for(unsigned int s_ix=0; s_ix<num_of_registered_sensors; s_ix++) {
			csv_writer->write_field(registered_sensors[s_ix]->get_name());
			csv_writer->make_new_field();
		}

		for(unsigned int a_ix=0; a_ix<num_of_registered_agents; a_ix++) {

			csv_writer->write_field(registered_agents[a_ix]->get_name());
			csv_writer->make_new_field();

		}

		csv_writer->write_field("confidence counter");
		csv_writer->make_new_field();

		csv_writer->make_new_line();
	}


	//TODO: HIER ENDLOSSCHLEIFE ODER SO - Irgendwas, dass stoppt, wenn file zu ende
	for(unsigned int sec=1; sec<=29208; sec++) {

		printf("second %u\n", sec);

		if(flag_csv_writer_exist) {
			csv_writer->write_field((int)sec);
			csv_writer->make_new_field();
		}


		//Update Sensor Values
		for(unsigned int s_ix = 0; s_ix < num_of_registered_sensors; s_ix++) {
			//TODO: make possibility of non-registered csv-reader
			if(flag_sensor_has_csvr[s_ix]) {

				float value_from_csv;
				
				if(registered_sensors_csvr[s_ix] != NULL) {

					if(registered_sensors_csvr[s_ix]->get_next_value(&value_from_csv)) {

						registered_sensors[s_ix]->update_sensor_value(value_from_csv);

						//printf("field of %s: %f", registered_sensors[s_ix]->get_name(), value_from_csv);
					}
				}
			}
		}


		for(unsigned int s_ix = 0; s_ix < num_of_registered_sensors; s_ix++) {
			registered_sensors[s_ix]->trigger();
			
			if(flag_csv_writer_exist) {
				if(registered_sensors[s_ix]->get_flag_sensor_value_is_valid()) {
					csv_writer->write_field(registered_sensors[s_ix]->get_sensor_value());
				}
				csv_writer->make_new_field();
			}
		}
	




		for(unsigned int c_ix = 0; c_ix < num_of_registered_channels; c_ix++) {

			//printf("\n\n\nTRIGGER CHANNELS\n");

			registered_channels[c_ix]->trigger();
		}






		for(unsigned int a_ix = 0; a_ix < num_of_registered_agents; a_ix++) {

			registered_agents[a_ix]->trigger();

			if(flag_csv_writer_exist) {

				if(registered_agents[a_ix]->get_flag_bunched_score_exist()) {
					csv_writer->write_field(registered_agents[a_ix]->get_bunched_score());
					csv_writer->make_new_field();
					csv_writer->write_field((int)registered_agents[a_ix]->get_bunch_score_confidency());
				}
				else if(registered_agents[a_ix]->get_flag_abstracted_sensor_score_exist(0)) {
					csv_writer->write_field(registered_agents[a_ix]->get_abstracted_sensor_score(0));
				}
				
				if(a_ix < num_of_registered_agents-1) {
					csv_writer->make_new_field();
				}
			}
		}

		if(flag_csv_writer_exist) {
			csv_writer->make_new_line();
		}


		getchar();

	}


	if(flag_csv_writer_exist) {
		csv_writer->close_file();
	}
	

}

//for agents:
unsigned int Testbench :: get_num_of_registered_agents() {
	return num_of_registered_agents;
}

bool Testbench :: register_agent(Agent *agent) {
	if(num_of_registered_agents < MAX_NUM_OF_AGENTS) {
		registered_agents[num_of_registered_agents] = agent;
		num_of_registered_agents++;
		return true;
	}
	return false;
}

bool Testbench :: deregister_agent(Agent *agent) {
	unsigned int agent_ix;
	
	if(get_ix_of_agent(agent, &agent_ix)) {
		return deregister_agent(agent_ix);
	}

	return false;
}

bool Testbench :: deregister_agent(unsigned int agent_ix) {
	if(agent_ix < num_of_registered_agents) {
		for(unsigned int a_ix=agent_ix; a_ix<num_of_registered_agents-1; a_ix++) {
			registered_agents[a_ix] = registered_agents[a_ix+1];
		}
		num_of_registered_agents--;

		return true;
	}
	return false;
}

bool Testbench :: get_ix_of_agent(Agent *agent, unsigned int *agent_ix) {
	for(unsigned int a_ix=0; a_ix<num_of_registered_agents; a_ix++) {
		if(registered_agents[a_ix] == agent) {
			*agent_ix = a_ix;
			return true;
		}
	}
	return false;
}


//for sensors:
unsigned int Testbench :: get_num_of_registered_sensors() {
	return num_of_registered_sensors;
}

bool Testbench :: register_sensor(Sensor* sensor) {
	if(num_of_registered_sensors < MAX_NUM_OF_SENSORS) {
		registered_sensors[num_of_registered_sensors] = sensor;
		num_of_registered_sensors++;
		return true;
	}
	return false;
}

bool Testbench :: register_sensor(Sensor* sensor, CSV_Reader *csvr) {
	if(num_of_registered_sensors < MAX_NUM_OF_SENSORS) {
		registered_sensors[num_of_registered_sensors] = sensor;
		registered_sensors_csvr[num_of_registered_sensors] = csvr;
		flag_sensor_has_csvr[num_of_registered_sensors] = true;

		num_of_registered_sensors++;
		return true;
	}

	return false;
}

bool Testbench :: deregister_sensor(Sensor* sensor) {
	unsigned int sensor_ix;
	
	if(get_ix_of_sensor(sensor, &sensor_ix)) {
		return deregister_sensor(sensor_ix);
	}

	return false;
}

bool Testbench :: deregister_sensor(unsigned int sensor_ix) {
	if(sensor_ix < num_of_registered_sensors) {
		for(unsigned int s_ix=sensor_ix; s_ix<num_of_registered_sensors-1; s_ix++) {
			registered_sensors[s_ix] = registered_sensors[s_ix+1];
			//todo: next 2 lines are untested - test then
			registered_sensors_csvr[s_ix] = registered_sensors_csvr[s_ix+1];
			flag_sensor_has_csvr[s_ix] = flag_sensor_has_csvr[s_ix+1];
		}
		num_of_registered_sensors--;

		return true;
	}
	return false;
}

bool Testbench :: get_ix_of_sensor(Sensor* sensor, unsigned int *sensor_ix) {
	for(unsigned int s_ix=0; s_ix<num_of_registered_sensors; s_ix++) {
		if(registered_sensors[s_ix] == sensor) {
			*sensor_ix = s_ix;
			return true;
		}
	}
	return false;
}

bool Testbench :: get_flag_sensor_has_csvr(unsigned int sensor_ix) {
	return flag_sensor_has_csvr[sensor_ix];
}

CSV_Reader* Testbench :: get_registered_sensors_csvr(unsigned int sensor_ix) {
	if(flag_sensor_has_csvr[sensor_ix]) {
		return registered_sensors_csvr[sensor_ix];
	}
	return NULL;
}

//TODO: test following function! ...until now it is untested
CSV_Reader* Testbench :: get_registered_sensors_csvr(Sensor* sensor) {
	unsigned int sensor_ix;

	if(get_ix_of_sensor(sensor, &sensor_ix)) {
		if(flag_sensor_has_csvr[sensor_ix]) {
			return registered_sensors_csvr[sensor_ix];
		}	
	}

	return NULL;
}






//for channels:
unsigned int Testbench :: get_num_of_registered_channels() {
	return num_of_registered_channels;
}

bool Testbench :: register_channel(Channel* channel) {
	if(num_of_registered_channels < MAX_NUM_OF_CHANNELS) {
		registered_channels[num_of_registered_channels] = channel;
		num_of_registered_channels++;
		return true;
	}
	return false;
}

bool Testbench :: deregister_channel(Channel* channel) {
	unsigned int channel_ix;

	if(get_ix_of_channel(channel, &channel_ix)) {
		return deregister_channel(channel_ix);
	}

	return false;
}

bool Testbench :: deregister_channel(unsigned int channel_ix) {
	if(channel_ix < num_of_registered_channels) {
		for(unsigned int c_ix=channel_ix; c_ix<num_of_registered_channels-1; c_ix++) {
			registered_channels[channel_ix] = registered_channels[channel_ix+1];
		}
		num_of_registered_channels--;

		return true;
	}
	return false;
}

bool Testbench :: get_ix_of_channel(Channel* channel, unsigned int *channel_ix) {
	for(unsigned int c_ix=0; c_ix<num_of_registered_channels; c_ix++) {
		if(registered_channels[c_ix] == channel) {
			*channel_ix = c_ix;
			return true;
		}
	}
	return false;
}

bool Testbench :: register_csv_reader(CSV_Reader* csv_reader) {
	if(csv_reader != NULL) {
		this->csv_reader = csv_reader;
		flag_csv_reader_exist = true;
		return true;
	}
	return false;
}

bool Testbench :: register_csv_writer(CSV_Writer* csv_writer) {
	if(csv_writer != NULL) {
		this->csv_writer = csv_writer;
		flag_csv_writer_exist = true;
		return true;
	}
	return false;
}
*/
