#ifndef STATEHANDLER_HEADERFILE
#define STATEHANDLER_HEADERFILE

#include "Module.h"
#include "SlaveAgentSlotOfAgent.h"
#include "State.h"

#include "StateVariable.h"
#include <vector>

//XXX - only for now
#include "CSV_Writer.h"
#include "LinearFunctionBlock.h"


using namespace std;


class StateHandler : public Module {
	public:
		LinearFunctionBlock* StabSamples;
		LinearFunctionBlock* StabDeviation;
		LinearFunctionBlock* UnstabDeviation;
		LinearFunctionBlock* SameState;
		LinearFunctionBlock* DriftDeviation;
		LinearFunctionBlock* BrokenCounterSamples;
		LinearFunctionBlock* ValidState;

		//NEU:
		//compare
		LinearFunctionBlock* FuncBlockConfSim2StateDev;
		LinearFunctionBlock* FuncBlockConfDif2StateDev;
		LinearFunctionBlock* FuncBlockConfSim2StateTime;
		LinearFunctionBlock* FuncBlockConfDif2StateTime;
		//insert
		LinearFunctionBlock* FuncBlockConfValStateDev;
		LinearFunctionBlock* FuncBlockConfInvStateDev;
		LinearFunctionBlock* FuncBlockConfValStateTime;
		LinearFunctionBlock* FuncBlockConfInvStateTime;

		LinearFunctionBlock* FuncBlockConfBrokenSamples;





	private:

		//DATE18
		//XXX - >0,5?
		//discreate Average Partition Size adjustable?
		float confidenceStableInput;
		float confidenceStableOutput;
		float confidenceStable;
		float confStableAdjustableThreshold;

		float confidenceUnstableInput;
		float confidenceUnstableOutput;
		float confidenceUnstable;
		float confidenceUnstableAdjustableThreshold;

		float confidenceSameStateInput;
		float confSameStateInputAdjustableThreshold;
		float confidenceSameStateOutput;
		float confSameStateOutputAdjustableThreshold;

		float confidenceValidState;
		float confValidStateAdjustableThreshold;

		unsigned int brokenCounter;
		float confidenceBroken;
		float confidenceBrokenAdjustableThreshold;

		unsigned int driftCounter;
		float confidenceDrift;
		float confidenceDriftAdjustableThreshold;



		//XXX - Maybe Object "StateVariable" between StateHandler and Slot?!
		vector<SlaveAgentSlotOfAgent*> vInputVariables;
		vector<SlaveAgentSlotOfAgent*> vOutputVariables;

		vector<State*> vStates;
		State* activeState;
		unsigned int minNumToBeValidState;
		
		bool flagVariablesWereStable;
		unsigned int slidingWindowBufferSize;
		unsigned int minNumOfRelatedValuesToBeStable;
		float thresholdToBeStable;

		float thresholdToBeRelated;

		unsigned int discreteAveragePartitionSize;
		unsigned int compareDistanceDiscreteAveragePartition;
		float thresholdNotDrift;

		unsigned int maxStateHistoryLength;

		void initStateHandler();

		bool addVariable(vector<SlaveAgentSlotOfAgent*>* vVariables, SlaveAgentSlotOfAgent* slot);
		bool variablesAreStable(vector<SlaveAgentSlotOfAgent*>* vVariables);

		//DATE18
		float getConfVariableIsStable(SlaveAgentSlotOfAgent* variable);
		float getConfVariablesAreStable(vector<SlaveAgentSlotOfAgent*>* vVariables);
		float getConfVariableIsUnstable(SlaveAgentSlotOfAgent* variable);
		float getConfVariablesAreUnstable(vector<SlaveAgentSlotOfAgent*>* vVariables);

		//bool getConfAndUnconfVariableIsMatching(SlaveAgentSlotOfAgent* variable, LinearFunctionBlock* confDeviation, LinearFunctionBlock* confTime, float* conf, float* unconf);
		bool getConfAndUnconfVariableIsMatching(State* state, LinearFunctionBlock* confDeviation, LinearFunctionBlock* confTime, float* conf, float* unconf);
		bool getConfAndUnconfVariablesAreMatching(vector<SlaveAgentSlotOfAgent*>* vVariables, LinearFunctionBlock* confDeviation, LinearFunctionBlock* confTime, float* conf, float* unconf);


		State* makeNewState();

		string create_Output_File_Name(string cfg_Parameter);

		bool addActiveStateToStateVector();
		//bool addStateAndMakeItActive();

		bool makeNewActiveState();

		State* findRelatedState();
		bool findRelatedStateAndMakeItActive();

		void eraseStatesWithLessInjections();

		bool delete_all_OuputVariables();
		bool delete_all_InputVariables();
		bool delete_allStates();
		//XXX - only for now:
        CSV_Writer *csv_writer;



	public:
		StateHandler();
		StateHandler(char* name);

		bool setDiscreteAveragePartitionSize(unsigned int discreteAverage);
		unsigned int getDiscreteAveragePartitionSize();

		bool addInputVariable(SlaveAgentSlotOfAgent* slot);
		bool addOutputVariable(SlaveAgentSlotOfAgent* slot);

		bool setSlidingWindowBufferSize(unsigned int slidingWindowBufferSize);
		bool setMinNumOfRelatedValuesToBeStable(unsigned int minNumOfRelatedValuesToBeStable);
		bool setThresholdToBeStable(float thresholdToBeStable);

		bool setThresholdToBeRelated(float thresholdToBeRelated);

		void trigger(unsigned int cycle);
		
		//XXX - only for now
		void closeCsvFile();

		void set_CSV_Writer_parameter(string cfg_parameter);
		void reset_States();
		void reset_States_and_Slave_Agents();

		~StateHandler();



	/*
	private:
		vector<SlaveAgentSlotOfAgent*> vSlots;

		unsigned int minNumOfChangedForValidStateChange;
		
		unsigned int minimumInjectionsForBeingState;

		void initStateHandler();

	public:
		StateHandler();
		StateHandler(char* name);

		bool setMinimumInjectionsForBeingState(unsigned int minimumInjectionsForBeingState);
		unsigned int getMinimumInjectionsForBeingState();

		//TODO: function for deleting slot and function with the whole vector as parameter
		bool add_slot(SlaveAgentSlotOfAgent* slot);

		void set_minNumOfChangedForValidStateChange(unsigned int minNumOfChangedForValidStateChange);
		unsigned int get_minNumOfChangedForValidStateChange();

		bool trigger();
	*/
};

#endif
