#include "SetupOLD.h"
#include "rlutil.h"

using namespace rlutil;

SetupOLD::SetupOLD() {

}



void SetupOLD::printMountingProcessImpossible() {
	setColor(LIGHTRED);
	printf(" > Process of Mounting is impossible\n");
	setColor(GREY);
}

void SetupOLD::printAgentGotMounted(Agent* masterAgent, Agent* slaveAgent) {
	printf(" > Agent ");
	setColor(LIGHTCYAN);
	printf("%s ", slaveAgent->getName().c_str());
	setColor(GREY);
	printf("(%03u) ", slaveAgent->getId());
	setColor(LIGHTGREEN);
	printf("mounted ");
	setColor(GREY);
	printf("in Agent ");
	setColor(LIGHTCYAN);
	printf("%s ", masterAgent->getName().c_str());
	setColor(GREY);
	printf("(%03u)\n", masterAgent->getId());
}

void SetupOLD::printAgentCouldntGetMounted(Agent* masterAgent, Agent* slaveAgent) {
	setColor(LIGHTRED);
	printf(" > Agent %s (%03u) couldn't get mounted in Agent %s (%03u)\n", slaveAgent->getName().c_str(), slaveAgent->getId(), masterAgent->getName().c_str(), masterAgent->getId());
	setColor(GREY);
}

void SetupOLD::printHistoryModuleGotMounted(Agent* agent, HistoryModule* historyModule) {
	printf(" > History Module ");
	setColor(LIGHTCYAN);
	printf("%s ", historyModule->getName().c_str());
	setColor(GREY);
	printf("(%03u) ", historyModule->getId());
	setColor(LIGHTGREEN);
	printf("mounted ");
	setColor(GREY);
	printf("in Agent ");
	setColor(LIGHTCYAN);
	printf("%s ", agent->getName().c_str());
	setColor(GREY);
	printf("(%03u)\n", agent->getId());
}

void SetupOLD::printHistoryModuleCouldntGetMounted(Agent* agent, HistoryModule* historyModule) {
	setColor(LIGHTRED);
	printf(" > History Module %s (%03u) couldn't get mounted in Agent %s (%03u)\n", historyModule->getName().c_str(), historyModule->getId(), agent->getName().c_str(), agent->getId());
	setColor(GREY);
}

void SetupOLD::printSensorGotMounted(Agent* agent, Sensor* sensor) {
	printf(" > Sensor ");
	setColor(LIGHTCYAN);
	printf("%s ", sensor->getName().c_str());
	setColor(GREY);
	printf("(%03u) ", sensor->getId());
	setColor(LIGHTGREEN);
	printf("mounted ");
	setColor(GREY);
	printf("in Agent ");
	setColor(LIGHTCYAN);
	printf("%s ", agent->getName().c_str());
	setColor(GREY);
	printf("(%03u)\n", agent->getId());
}

void SetupOLD::printSensorCouldntGetMounted(Agent* agent, Sensor* sensor) {
	setColor(LIGHTRED);
	printf(" > Agent %s (%03u) couldn't get mounted in Agent %s (%03u)\n", sensor->getName().c_str(), sensor->getId(), agent->getName().c_str(), agent->getId());
	setColor(GREY);
}


void SetupOLD::printStabilityModuleGotMounted(Agent* agent, StabilityModule* stabilityModule) {
	printf(" > Stability Module ");
	setColor(LIGHTCYAN);
	printf("%s ", stabilityModule->getName().c_str());
	setColor(GREY);
	printf("(%03u) ", stabilityModule->getId());
	setColor(LIGHTGREEN);
	printf("mounted ");
	setColor(GREY);
	printf("in Agent ");
	setColor(LIGHTCYAN);
	printf("%s ", agent->getName().c_str());
	setColor(GREY);
	printf("(%03u)\n", agent->getId());
}

void SetupOLD::printStabilityModuleCouldntGetMounted(Agent* agent, StabilityModule* stabilityModule) {
	setColor(LIGHTRED);
	printf(" > Stability Module %s (%03u) couldn't get mounted in Agent %s (%03u)\n", stabilityModule->getName().c_str(), stabilityModule->getId(), agent->getName().c_str(), agent->getId());
	setColor(GREY);
}


void SetupOLD::printConnectionEstablished(Agent* hostAgent, HistoryModule* historyModule, Agent* slaveAgent) {
	printf(" > Inside of Agent ");
	setColor(LIGHTCYAN);
	printf("%s ", hostAgent->getName().c_str());
	setColor(GREY);
	printf("(%03u): ", hostAgent->getId());
	printf("History Module ");
	setColor(LIGHTCYAN);
	printf("%s ", historyModule->getName().c_str());
	setColor(GREY);
	printf("(%03u) is ", historyModule->getId());
	setColor(LIGHTGREEN);
	printf("connected ");
	setColor(GREY);
	printf("with Input of Agent ");
	setColor(LIGHTCYAN);
	printf("%s ", slaveAgent->getName().c_str());
	setColor(GREY);
	printf("(%03u)\n", slaveAgent->getId());
}

void SetupOLD::printConnectionEstablished(Agent* hostAgent, StabilityModule* stabilityModule, HistoryModule* historyModule, Agent* slaveAgent) {
	printf(" > Inside of Agent ");
	setColor(LIGHTCYAN);
	printf("%s ", hostAgent->getName().c_str());
	setColor(GREY);
	printf("(%03u): ", hostAgent->getId());
	printf("Stability Module ");
	setColor(LIGHTCYAN);
	printf("%s ", stabilityModule->getName().c_str());
	setColor(GREY);
	printf("(%03u) is ", stabilityModule->getId());
	setColor(LIGHTGREEN);
	printf("connected ");
	setColor(GREY);
	printf("with Input of Agent ");
	setColor(LIGHTCYAN);
	printf("%s ", slaveAgent->getName().c_str());
	setColor(GREY);
	printf("(%03u) and ", slaveAgent->getId());
	printf("with History Module ");
	setColor(LIGHTCYAN);
	printf("%s ", historyModule->getName().c_str());
	setColor(GREY);
	printf("(%03u)\n", historyModule->getId());
}

void SetupOLD::printConnectionIsImpossible() {
	setColor(LIGHTRED);
	printf(" > Process of Connecting is impossible\n");
	setColor(GREY);
}



void SetupOLD::mountAgentInAgent(Agent* masterAgent, Agent* slaveAgent, Channel* channel) {
	if (masterAgent && slaveAgent && channel) {
		//note: next line is because one slaveAgent can only be mounted once
		if (!agentIsRegistered(slaveAgent) || !getRegisteredAgent(slaveAgent)->masterAgentIsSet()) {

			SetupAgent* setupSlaveAgent = NULL;
			
			if (agentIsRegistered(slaveAgent)) {
				setupSlaveAgent = getRegisteredAgent(slaveAgent);
			}
			else {
				setupSlaveAgent = registerAgent(slaveAgent);
			}
			
			SetupAgent* setupMasterAgent = NULL;

			if (agentIsRegistered(masterAgent)) {
				setupMasterAgent = getRegisteredAgent(masterAgent);
			}
			else {
				setupMasterAgent = registerAgent(masterAgent);
			}

			if (setupMasterAgent->mountAgent(slaveAgent, channel)) {
				if (setupSlaveAgent->setMasterAgent(masterAgent, channel)) {
					printAgentGotMounted(masterAgent, slaveAgent);
				}
				else {
					//TODO: unmount in real and in setup object
				}
			}
		}
	}
}

SetupAgent* SetupOLD::registerAgent(Agent* agent) {
	SetupAgent* setupAgent = new SetupAgent(agent);
	try {
		vSetupAgents.push_back(setupAgent);
		return setupAgent;
	}
	catch (bad_alloc& error) {
		delete setupAgent;
	}
	return NULL;
}

bool SetupOLD::agentIsRegistered(Agent* agent) {
	for (auto &registeredAgent : vSetupAgents)
		if (registeredAgent->getAgent() == agent)
			return true;
	return false;
}

SetupAgent* SetupOLD::getRegisteredAgent(Agent* agent) {
	for (auto &registeredAgent : vSetupAgents)
		if (registeredAgent->getAgent() == agent) {
			printf("DADRINN\n\n");
			return registeredAgent;
		}
			
	return NULL;
}



void SetupOLD::mountSensorInAgent(Agent* agent, Sensor* sensor, Channel* channel) {
	if (agent && sensor && channel) {
		//note: next line is because one sensor can only be mounted once
		if (!SensorIsRegistered(sensor)) {
			SetupSensor* setupSensor = registerSensor(sensor);
			SetupAgent* setupAgent = NULL;

			if (agentIsRegistered(agent)) {
				setupAgent = getRegisteredAgent(agent);
			}
			else {
				setupAgent = registerAgent(agent);
			}


			if (setupAgent->mountSensor(sensor, channel)) {
				if (setupSensor->setMasterAgent(agent, channel)) {
					printSensorGotMounted(agent, sensor);
				}
				else {
					//TODO: unmount in real and in setup object
				}
			}
		}
	}
}

SetupSensor* SetupOLD::registerSensor(Sensor* sensor) {
	SetupSensor* setupSensor = new SetupSensor(sensor);
	try {
		vSetupSensors.push_back(setupSensor);
		return setupSensor;
	}
	catch (bad_alloc& error) {
		delete setupSensor;
	}
	return NULL;
}

bool SetupOLD::SensorIsRegistered(Sensor* sensor) {
	for (auto &registeredSensor : vSetupSensors)
		if (registeredSensor->getSensor() == sensor)
			return true;
	return false;
}

SetupSensor* SetupOLD::getRegisteredSensor(Sensor* sensor) {
	for (auto &registeredSensor : vSetupSensors)
		if (registeredSensor->getSensor() == sensor)
			return registeredSensor;
	return NULL;
}



void SetupOLD::mountHistoryModuleInAgent(Agent* agent, HistoryModule* historyModule) {
	if (agent && historyModule) {
		//NOTE: next line is because a history module can only be mounted once
		if (!historyModuleIsRegistered(historyModule)) {
			SetupMountedHistoryModule* setupMountedHistoryModule = registerHistoryModule(historyModule);
			SetupAgent* setupAgent = NULL;

			if (agentIsRegistered(agent)) {
				setupAgent = getRegisteredAgent(agent);
			}
			else {
				setupAgent = registerAgent(agent);
			}

			if (setupAgent->mountHistoryModule(setupMountedHistoryModule)) {
				printHistoryModuleGotMounted(agent, historyModule);
				return;
			}
		}
		printHistoryModuleCouldntGetMounted(agent, historyModule);
		return;
	}
	printMountingProcessImpossible();
}

SetupMountedHistoryModule* SetupOLD::registerHistoryModule(HistoryModule* historyModule) {
	SetupMountedHistoryModule* setupMountedHistoryModule = new SetupMountedHistoryModule(historyModule);
	try {
		vSetupHistoryModules.push_back(setupMountedHistoryModule);
		return setupMountedHistoryModule;
	}
	catch (bad_alloc& error) {
		delete setupMountedHistoryModule;
	}
	return NULL;
}

bool SetupOLD::historyModuleIsRegistered(HistoryModule* historyModule) {
	for (auto &registeredHistoryModule : vSetupHistoryModules)
		if (registeredHistoryModule->getHistoryModule() == historyModule)
			return true;
	return false;
}

SetupMountedHistoryModule* SetupOLD::getRegisteredHistoryModule(HistoryModule* historyModule) {
	for (auto &registeredHistoryModule : vSetupHistoryModules)
		if (registeredHistoryModule->getHistoryModule() == historyModule)
			return registeredHistoryModule;
	return NULL;
}


//TODO: it is the same as the mountHistoryModule function -> template
void SetupOLD::mountStabilityModules(Agent* agent, StabilityModule* stabilityModule) {
	if(agent && stabilityModule) {
		//NOTE: next line is because a history module can only be mounted once
		if (!stabilityModuleIsRegistered(stabilityModule)) {
			SetupStabilityModule* setupStabilityModule = registerStabilityModule(stabilityModule);
			SetupAgent* setupAgent = NULL;

			if (agentIsRegistered(agent)) {
				setupAgent = getRegisteredAgent(agent);
			}
			else {
				setupAgent = registerAgent(agent);
			}

			if (setupAgent->mountStabilityModule(setupStabilityModule)) {
				printStabilityModuleGotMounted(agent, stabilityModule);
				return;
			}
		}
		printStabilityModuleCouldntGetMounted(agent, stabilityModule);
		return;
	}
	printMountingProcessImpossible();
}

SetupStabilityModule* SetupOLD::registerStabilityModule(StabilityModule* stabilityModule) {
	SetupStabilityModule* setupStabilityModule = new SetupStabilityModule(stabilityModule);
	try {
		vSetupStabilityModules.push_back(setupStabilityModule);
		return setupStabilityModule;
	}
	catch (bad_alloc& error) {
		delete setupStabilityModule;
	}
	return NULL;
}

bool SetupOLD::stabilityModuleIsRegistered(StabilityModule* stabilityModule) {
	for (auto &registeredStabilityModule : vSetupStabilityModules)
		if (registeredStabilityModule->getStabilityModule() == stabilityModule)
			return true;
	return false;
}

SetupStabilityModule* SetupOLD::getRegisteredStabilityModule(StabilityModule* stabilityModule) {
	for (auto &registeredStabilityModule : vSetupStabilityModules)
		if (registeredStabilityModule->getStabilityModule() == stabilityModule)
			return registeredStabilityModule;
	return NULL;
}



void SetupOLD::connect(HistoryModule* historyModule, Agent* slaveAgent) {
	if (historyModule && slaveAgent) {
		if (historyModuleIsRegistered(historyModule) && agentIsRegistered(slaveAgent)) {

			SetupMountedHistoryModule* registeredHistoryModule = getRegisteredHistoryModule(historyModule);
			Agent* hostAgent = registeredHistoryModule->getHostAgent();

			printf("das is interessant\n");
			SetupAgent* mountedAgent = getRegisteredAgent(slaveAgent);

			if (hostAgent == mountedAgent->getMasterAgent()) {
				//next line connect for real
				if (historyModule->setObservationPointer(mountedAgent->getAgentSlot()->getObservationPointer())) {
					printConnectionEstablished(hostAgent, historyModule, slaveAgent);
					return;
				}
			}
		}
	}
	printConnectionIsImpossible();
}

void SetupOLD::connect(HistoryModule* historyModule, Sensor* sensor) {
	printConnectionIsImpossible();
}	

void SetupOLD::connect(StabilityModule* stabilityModule, Agent* slaveAgent, HistoryModule* historyModule) {
	if (stabilityModule && slaveAgent && historyModule) {
		if (stabilityModuleIsRegistered(stabilityModule) && agentIsRegistered(slaveAgent) && historyModuleIsRegistered(historyModule)) {


			SetupStabilityModule* registeredStabilityModule = getRegisteredStabilityModule(stabilityModule);
			Agent* hostAgent = registeredStabilityModule->getHostAgent();
			SetupMountedHistoryModule* registeredHistoryModule = getRegisteredHistoryModule(historyModule);
			SetupAgent* mountedAgent = getRegisteredAgent(slaveAgent);
			if (hostAgent == registeredHistoryModule->getHostAgent() && hostAgent == mountedAgent->getMasterAgent()) {
				//next line connect for real
				if (stabilityModule->setObservationPointer(mountedAgent->getAgentSlot()->getObservationPointer(), historyModule->getObservationPointer())) {
					printConnectionEstablished(hostAgent, stabilityModule, historyModule, slaveAgent);
					return;
				}
			}
		}
	}
	printConnectionIsImpossible();
}
