#include "SlaveAgentSlotOfAgent.h"

#include "printError.h"
#include "relationChecker.h"

SlaveAgentSlotOfAgent :: SlaveAgentSlotOfAgent() {
	flagSlaveAgentValueIsSet = false;
	/*
	flagSlaveAgentValueHasChanged = false;
	flagSlaveAgentValueChangeIsSet = false;
	/*
	activeState = NULL;
	backupState = NULL;
	*/
}

void SlaveAgentSlotOfAgent :: setSlaveAgentValue(float slaveAgentValue) {
	this->slaveAgentValue = slaveAgentValue;
	flagSlaveAgentValueIsSet = true;
		
	/*
	if(flagSlaveAgentValueIsSet == false) {
		this->slaveAgentValue = slaveAgentValue;
		flagSlaveAgentValueIsSet = true;
		flagSlaveAgentValueHasChanged = true;
	}
	else {
		if(this->slaveAgentValue != slaveAgentValue) {
			flagSlaveAgentValueHasChanged = true;
			flagSlaveAgentValueChangeIsSet = true;
			slaveAgentValueChange = slaveAgentValue - this->slaveAgentValue;
			this->slaveAgentValue = slaveAgentValue;
		}
		else {
			flagSlaveAgentValueHasChanged = false;
			flagSlaveAgentValueChangeIsSet = true;
			slaveAgentValueChange = 0;
		}
	}
	*/
	//printf("slaveAgentSlot updated with: %f\n", this->slaveAgentValue);
}

bool SlaveAgentSlotOfAgent :: get_slaveAgentValue(float* slaveAgentValue) {
	if(flagSlaveAgentValueIsSet == true) {
		*slaveAgentValue = this->slaveAgentValue;
		return true;
	}
	return false;
}

bool SlaveAgentSlotOfAgent :: get_flagSlaveAgentValueIsSet() {
	return flagSlaveAgentValueIsSet;
}

//TODO: move these functions into -> HistoryHandler
bool SlaveAgentSlotOfAgent::saveValueInHistory() {
	if (flagSlaveAgentValueIsSet) {
		try {
			//printf("history saving - value: %f\n", slaveAgentValue);
			lSlaveAgentHistory.push_back(slaveAgentValue);
			return true;
		}
		catch (bad_alloc& error) {
			printError("bad_alloc caught: ", error.what());
		}
	}
	return false;
}
unsigned int SlaveAgentSlotOfAgent::getHistoryLength() {
	return lSlaveAgentHistory.size();
}
bool SlaveAgentSlotOfAgent::deleteOldestHistoryEntry() {
	if (!lSlaveAgentHistory.empty()) {
		lSlaveAgentHistory.pop_front();
		return true;
	}
	return false;
}


unsigned int SlaveAgentSlotOfAgent::getNumberOfRelativesToActualValue(float threshold) {
	unsigned int numberOfRelativesToActualValue = 0;
	for (auto &entry : lSlaveAgentHistory) {
		if (valueIsRelatedToReferenceValue(slaveAgentValue, entry, threshold)) {
		//if (valueIsRelatedToReferenceValueCanberra(slaveAgentValue, entry, threshold)) {
			numberOfRelativesToActualValue++;
		}
	}
	return numberOfRelativesToActualValue;
}





void SlaveAgentSlotOfAgent::printHistory() {
	printf("History: ");
	for (auto &entry : lSlaveAgentHistory) {
		printf("%f, ", entry);
	}
	printf("\n");
}


/*
bool SlaveAgentSlotOfAgent :: get_flagSlaveAgentValueHasChanged() {
	return flagSlaveAgentValueHasChanged;
} 

bool SlaveAgentSlotOfAgent :: get_slaveAgentValueChangingRate(float* slaveAgentValueChangingRate) {
	if(flagSlaveAgentValueChangeIsSet) {
		*slaveAgentValueChangingRate = this->slaveAgentValueChange;
		return true;
	}
	return false;
}

/*
bool SlaveAgentSlotOfAgent :: addStateToStatesVector(State* state) {
	if (state != NULL) {
		try {
			vStates.push_back(state);
			return true;
		}
		catch (bad_alloc& error) {
			printError("bad_alloc caught: ", error.what());
			delete state;
		}

	}
	return false;
}


vector<State*>* SlaveAgentSlotOfAgent :: getStatesVector() {
	return &vStates;
}


bool SlaveAgentSlotOfAgent :: createNewStateAndMakeItActive() {
	State* state = new State();
	if (addStateToStatesVector(state)) {
		backupState = activeState;
		activeState = state;
		return true;
	}
	return false;
}

bool SlaveAgentSlotOfAgent :: injectValueInActiveState() {
	if (activeState == NULL) {
		if (createNewStateAndMakeItActive()) {
			return activeState->injectValue(slaveAgentValue);
		}
	}
	return activeState->injectValue(slaveAgentValue);
}

int SlaveAgentSlotOfAgent :: getIndexOfRelatedState(unsigned int startIndex, float thresholdToAverage) {
	if (startIndex >= vStates.size())
		return -2;
	
	int index = 0;
	for (vector<State*>::iterator state = vStates.begin() + startIndex; state < vStates.end(); state++, index++) {
		if ((*state)->valueIsRelated(slaveAgentValue, thresholdToAverage)) {
			return index;
		}
	}

	return -1;
}

bool SlaveAgentSlotOfAgent :: relatedToActiveState(float thresholdToAverage) {
	printf("a\n");
	if (activeState == NULL) {
		printf("b\n");
		createNewStateAndMakeItActive();
		return true;
	}

	return activeState->valueIsRelated(slaveAgentValue, thresholdToAverage);
}

bool SlaveAgentSlotOfAgent :: valueIsRelated(unsigned int index, float thresholdToAverage) {
	return vStates[index]->valueIsRelated(slaveAgentValue, thresholdToAverage);
}

State* SlaveAgentSlotOfAgent :: getActiveState() {
	return activeState;
}

void SlaveAgentSlotOfAgent :: deleteActiveState() {
	//if(vStates.empty() == false)
	vStates.back()->deleteState();

	vStates.pop_back();

	if (backupState != NULL) {
		activeState = backupState;
		backupState = NULL;
	}
}

bool SlaveAgentSlotOfAgent :: setActiveState(unsigned int index) {
	if (vStates.size() > index) {
		activeState = vStates.at(index);
		return true;
	}
	return false;
}

unsigned int SlaveAgentSlotOfAgent::getNumberOfStates() {
	if (!vStates.empty())
		printf("%u - ", activeState->getNumberOfInjections());
	return vStates.size();
}
*/