#include "stdafx.h"
#include "SimulationController.h"
#include "StatisticsSimulatorObserver.h"
#include "DTOIterator.h"
#include "ResultDTOIteratorFactory.h"
#include <cassert>

SimulationController* SimulationController::_instance =0;

void SimulationController::setSimulationResult(AbstractSimulationResultDTO* simulationResult)
{
	_simulationResult = simulationResult;
}

void SimulationController::executeAction(AbstractAction* action){
	action->setSimulationController(this);
	action->execute();
}

void SimulationController::startSimulation(bool continuous, int numberOfSimulations)
{
	assert(numberOfSimulations >= 1);
	_simulator->setAverageArrivalsRate((int)_simulationParametersDTO->getAverageTimeOfArrivals());
	if (numberOfSimulations == 1 && continuous){
		_simulator->start();
		while(!_simulator->isSimulationComplete()){
			_simulator->step();
		}
		setSimulationResult(_simulator->getSimulationResult());
		notifySimulation();
	} else if (numberOfSimulations > 1 && continuous) {
		for (int i = 0; i < numberOfSimulations ; i++){
			_simulator->start();
			while(!_simulator->isSimulationComplete()){
				_simulator->step();
			}

		}
		setSimulationResult(_simulator->getSimulationResult());
		notifyMultipleSimulations();
	} else {
		_simulator->start();
		_simulator->step();
		setSimulationResult(_simulator->getSimulationResult());
		notifyStep();
	}
}

void SimulationController::setSimulator(AbstractSimulator *simulator)
{
	_simulator = simulator;
}

bool SimulationController::stepSimulation()
{
	if (_simulator->isSimulationComplete()){
		setSimulationResult(_simulator->getSimulationResult());
		notifySimulation();
		return false;
	}
	else { 
		_simulator->step();
		setSimulationResult(_simulator->getSimulationResult());
		notifyStep();
		return true;
	}
	
}

void SimulationController::stepSimulation(int stepInterval)
{
	for (int i = 0; i < stepInterval; i++){
		if (_simulator->isSimulationComplete()){
			setSimulationResult(_simulator->getSimulationResult());
			notifySimulation();
			return;
		}
		else { 
			_simulator->step();
			setSimulationResult(_simulator->getSimulationResult());
			notifyStep();
			return;
		}
	}
}


void SimulationController::setSimulationParametersDTO(SimulationParametersDTO *simulationParametersDTO)
{
	_simulationParametersDTO = simulationParametersDTO; 
}

AbstractSimulationResultDTO* SimulationController::getSimulationResult(){
	
	return _simulationResult; 
}
