#ifndef AGENT_HEADERFILE
#define AGENT_HEADERFILE

#include "MasterAgentHandlerOfAgent.h"
#include "Node.h"
#include "SensorHandlerOfAgent.h"
#include "SlaveAgentHandlerOfAgent.h"

/*
#include "Node.h"
#include "Sensor.h"
#include "HistoryModule.h"
#include "Channel.h"
#include "AbstractionModule.h"
#include "ConfidenceModule.h"
#include "Bunch_Module.h"
#include "Cross_Confidence_Validator.h"

#include "Slave_Agent_Handler.h"

//#include "Evaluation.h"

//TODO: options for less slaveagents and sensors (that means instead of comparing "< MAX_NUM_OF_" -> "< max_num_of_"
/*
#define YOU_HAVE_A_MASTER	   true
#define YOU_DONT_HAVE_A_MASTER false
*/

//#define ACTIVE true
//#define INACTIVE false

//#define MOUNTED   true
//#define UNMOUNTED false
/*
#define ARITHMETIC_MEAN			 0
#define GEOMETRIC_MEAN			 1
#define HARMONIC_MEAN			 2
#define WEIGHTED_ARITHMETIC_MEAN 3
#define WEIGHTED_GEOMETRIC_MEAN  4
#define WEIGHTED_HARMONIC_MEAN   5
*/

class Agent : public Node {

	private :
		SensorHandlerOfAgent* sensorHandlerOfAgent;
		SlaveAgentHandlerOfAgent* slaveAgentHandlerOfAgent;
		MasterAgentHandlerOfAgent* masterAgentHandlerOfAgent;

		void init_agent();

	public:
		Agent();
		Agent(char* name);

		bool set_sensorHandlerOfAgent();
		bool del_sensorHandlerOfAgent();
		SensorHandlerOfAgent* get_sensorHandlerOfAgent();
		
		bool set_slaveAgentHandlerOfAgent();
		bool del_slaveAgentHandlerOfAgent();
		SlaveAgentHandlerOfAgent* get_slaveAgentHandlerOfAgent();

		bool set_masterAgentHandlerOfAgent();
		bool del_masterAgentHandlerOfAgent();
		MasterAgentHandlerOfAgent* get_masterAgentHandlerOfAgent();


		void trigger();


	/*
	private:

		unsigned int working_frequency;

		//master agent
		bool flag_masteragent_is_mounted;
		Channel* mounted_masteragent_inputport;
		Channel* mounted_masteragent_outputport;
		bool flag_masteragent_inputport_is_active;
		bool flag_masteragent_outputport_is_active;


		//slave agents
		unsigned int num_of_mounted_slaveagents;
		bool flag_slaveagent_is_mounted[MAX_NUM_OF_MOUNTED_SLAVEAGENTS];
		bool flag_slaveagent_has_dedicated_position[MAX_NUM_OF_MOUNTED_SLAVEAGENTS];
		Channel* mounted_slaveagent_inputport[MAX_NUM_OF_MOUNTED_SLAVEAGENTS];
		Channel* mounted_slaveagent_outputport[MAX_NUM_OF_MOUNTED_SLAVEAGENTS];
		bool flag_slaveagent_inputport_is_active[MAX_NUM_OF_MOUNTED_SLAVEAGENTS];
		bool flag_slaveagent_outputport_is_active[MAX_NUM_OF_MOUNTED_SLAVEAGENTS];

		//slaveagent values
		int slaveagent_value[MAX_NUM_OF_MOUNTED_SENSORS];
		bool flag_slaveagent_value_set[MAX_NUM_OF_MOUNTED_SENSORS];
		bool flag_slaveagent_value_changed[MAX_NUM_OF_MOUNTED_SENSORS];

		//sensors
		unsigned int num_of_mounted_sensors;
		bool flag_sensor_is_mounted[MAX_NUM_OF_MOUNTED_SENSORS];
		bool flag_sensor_has_dedicated_position[MAX_NUM_OF_MOUNTED_SENSORS];
		Channel* mounted_sensor_inputport[MAX_NUM_OF_MOUNTED_SENSORS];
		bool flag_sensor_inputport_is_active[MAX_NUM_OF_MOUNTED_SENSORS];

		//sensor values
		float sensor_value[MAX_NUM_OF_MOUNTED_SENSORS];
		bool flag_sensor_value_set[MAX_NUM_OF_MOUNTED_SENSORS];
		bool flag_sensor_value_changed[MAX_NUM_OF_MOUNTED_SENSORS];

		//sensor history
		HistoryModule* sensor_history[MAX_NUM_OF_MOUNTED_SENSORS];
		bool flag_sensor_history_exist[MAX_NUM_OF_MOUNTED_SENSORS];

		//confidence 
		bool flag_confidence_validator_exist[MAX_NUM_OF_MOUNTED_SENSORS];
		ConfidenceModule* list_of_confidence_validators[MAX_NUM_OF_MOUNTED_SENSORS];
		bool flag_sensor_value_confident[MAX_NUM_OF_MOUNTED_SENSORS];
		
		bool flag_slaveagent_value_confident[MAX_NUM_OF_MOUNTED_SLAVEAGENTS];


		//abstraction modules
		bool flag_abstraction_exist[MAX_NUM_OF_MOUNTED_SENSORS];
		AbstractionModule* list_of_abstractions[MAX_NUM_OF_MOUNTED_SENSORS];
		int abstracted_sensor_score[MAX_NUM_OF_MOUNTED_SENSORS];
		bool flag_abstracted_sensor_score_exist[MAX_NUM_OF_MOUNTED_SENSORS];

		//bunch module
		bool flag_bunch_module_exist;
		Bunch_Module* bunch_module;
		int bunched_score;
		bool flag_bunched_score_exist;
		unsigned int bunch_score_confidency;

		//private functions
		void initialize_master_slot();
		void initialize_slaveagent_slots();
		void initialize_sensor_slots();
		void initialize_bunch_module();
		void initialize_working_frequency(int* success_indicator);

		//cross confidence
		Cross_Confidence_Validator* list_of_ccv_modules[MAX_NUM_OF_MOUNTED_SLAVEAGENTS];
		bool flag_ccv_module_exist[MAX_NUM_OF_MOUNTED_SLAVEAGENTS];

		bool read_mountedSensor(unsigned int s_ix);
		void read_all_mountedSensors();
		bool save_mountedSensor_history(unsigned int s_ix);
		void save_all_mountedSensor_histories();
		bool validate_confidence_of_mountedSensor(unsigned int s_ix);
		void validate_confidence_of_all_mountedSensors();
		bool read_slaveAgent(unsigned int sa_ix);
		void read_all_slaveAgents();

	public:
		// ----- Standard Attributes -----
		Agent();
		Agent(char* name);
		Agent(unsigned int working_frequency, int* success_indicator);
		Agent(char* name, unsigned int working_frequency, int* success_indicator);

		bool set_working_frequency(unsigned int working_frequency);

		// ----- Runtime Functions -----
		void trigger();

		// ----- Setup Subagents -----
		bool mount_slaveagent(Channel* inputport, Channel* outputport);
		bool mount_slaveagent(Channel* inputport, Channel* outputport, unsigned int position);
		bool mount_slaveagent(Channel* inputport, Channel* outputport, Cross_Confidence_Validator* ccv);

		bool mount_masteragent(Channel* inputport, Channel* outputport);


		// ----- Setup Mounted Sensors -----
		bool mount_sensor(Channel* inputport);
		bool mount_sensor(Channel* inputport, unsigned int position);
		bool mount_sensor(Channel* inputport, Abstraction* abstraction);
		bool mount_sensor(Channel* inputport, Confidence_Validator* confidence_validator);
		bool mount_sensor(Channel* inputport, HistoryModule* historyModule);
		bool mount_sensor(Channel* inputport, Confidence_Validator* confidence_validator, Abstraction* abstraction);

		// ----- Bunch Module -----
		bool mount_bunch_module(Bunch_Module* bunch_module);


		// ----- Setup Abstraction Method -----
		
		//bool set_abstraction_method(unsigned int abstraction_method);
		//unsigned int get_abstraction_method();
	


		//void set_agent_id(unsigned int id);
		//unsigned int get_agent_id();

		// ----- Setup Agent -----
		//TODO: DEACTIVATE, ACTIVATE (muss auch in miunt funktion an den Subagent weitergegeben werden)

		void set_active_state_flag(bool flag);
		bool get_active_state_flag();

		void set_master_agent(Agent* agent);
		void Agent :: register_as_master_agent(Agent* agent);
		void Agent :: deregister_as_master_agent();
		Agent* get_master_agent();

		bool get_flag_abstracted_sensor_score_exist(unsigned int position);
		int get_abstracted_sensor_score(unsigned int position);
		
		bool get_flag_bunched_score_exist();
		int get_bunched_score();
		
		unsigned int get_bunch_score_confidency();

		

		//test functions
		void test_print_all_slaveagents();
		void test_print_all_sensors();
		*/
};

#endif