#include "stdafx.h"
#include "StatisticsSimulatorObserver.h"
#include "SimulatorSingleton.h"
#include "SuitProcessor.h"
#include "Heap.h"
#include "Ptr.h"
#include "Event.h"
#include "StepResultDTO.h"
#include "ArrivalsInfoDTO.h"
#include "SimulationController.h"
#include "EvaluateFlaws.h"
#include "Suit.h"

StatisticsSimulatorObserver* StatisticsSimulatorObserver::_instance =0;

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

void StatisticsSimulatorObserver::updateStep(){

	stepResultDTO = new StepResultDTO();
	SuitProcessor *suitProcessor = SuitProcessor::instance();

	int numberArrivals = 0;
	int sizeQueueProcessSuit = 0;
	int sizeQueueProcessCoat = 0;
	int sizeQueueProcessPants = 0;
	int sizeQueueEvaluateFlaws = 0;
	int sizeQueueProcessFlaws = 0;
	
	int pantsStackSize = suitProcessor->getPantsStackSize();
	int coatStackSize = suitProcessor->getCoatStackSize();

	Event* currentEvent = simulator->getCurrentEvent();

	for (int i = 1; i <= simulator->getEventQueueSize(); i++) {

		Event* evt = simulator->getIthEvent(i);

		if (evt->getType() == 0) {
			numberArrivals++;
		}

		else if (evt->getType() == 1) {
			sizeQueueProcessSuit++;
		}

		else if (evt->getType() == 2) {
			sizeQueueProcessCoat++;
		}

		else if (evt->getType() == 3) {
			sizeQueueProcessPants++;
		}

		else if (evt->getType() == 4) {
			sizeQueueEvaluateFlaws++;
		}

		else if (evt->getType() == 5) {
			sizeQueueProcessFlaws++;
		}
		
		if (evt->getType() == currentEvent->getType()){
			double serviceTime = evt->getInitialTime() - evt->getTime();
		}
	}
	

	service1->updateQueue(sizeQueueProcessSuit);
	service2->updateQueue(sizeQueueProcessCoat);
	service3->updateQueue(sizeQueueProcessPants);
	service4Coats->updateQueue(coatStackSize);
	service4Pants->updateQueue(pantsStackSize);
	service4Suits->updateQueue(sizeQueueEvaluateFlaws);
	service5->updateQueue(sizeQueueProcessFlaws);

	if (currentEvent->getType() == 0)  // se for do tipo arrival
	{
		arrivals->updateNumberOfArrivals();
	}
	else if (currentEvent->getType() == 4)
	{
		EvaluateFlaws* evaluateFlaws = (EvaluateFlaws*)currentEvent;
		Suit suit = evaluateFlaws->suit;

		if (!suit.isFlawed())
			exits->updateExitsWithoutFlaw(suit.getEndTime() - suit.getInitialTime());
	}
	else if (currentEvent->getType() == 5) 
	{
		EvaluateFlaws* evaluateFlaws = (EvaluateFlaws*)currentEvent;
		Suit suit = evaluateFlaws->suit;

		exits->updateExitsWithFlaw(suit.getEndTime() - suit.getInitialTime());
	}

	service1->calculateData();
	service2->calculateData();
	service3->calculateData();
	service4Suits->calculateData();
	service4Pants->calculateData();
	service4Coats->calculateData();
	service5->calculateData();
	
	stepResultDTO->addSimulationResult(arrivals);
	stepResultDTO->addSimulationResult(service1);
	stepResultDTO->addSimulationResult(service2);
	stepResultDTO->addSimulationResult(service3);
	stepResultDTO->addSimulationResult(service4Suits);
	stepResultDTO->addSimulationResult(service4Coats);
	stepResultDTO->addSimulationResult(service4Pants);
	stepResultDTO->addSimulationResult(service5);
	stepResultDTO->addSimulationResult(exits);

	arrivals = dynamic_cast<ArrivalsInfoDTO*>(arrivals->clone());
	service1 = dynamic_cast<ServiceInfoDTO*>(service1->clone());
	service2 = dynamic_cast<ServiceInfoDTO*>(service2->clone());
	service3 = dynamic_cast<ServiceInfoDTO*>(service3->clone());
	service4Suits = dynamic_cast<ServiceInfoDTO*>(service4Suits->clone());
	service4Coats = dynamic_cast<ServiceInfoDTO*>(service4Coats->clone());
	service4Pants = dynamic_cast<ServiceInfoDTO*>(service4Pants->clone());
	service5 = dynamic_cast<ServiceInfoDTO*>(service5->clone());
	exits = dynamic_cast<ExitsInfoDTO*>(exits->clone());

	singleSimulationResultDTO->addSimulationResult(stepResultDTO);
	simulator->setSimulationResult(stepResultDTO);
	stepResultDTO->setID(stepCounter);
	stepCounter++;
	stepResultDTO = new StepResultDTO();
	
}
	
void StatisticsSimulatorObserver::updateSimulation(){
	multipleSimulationResultDTO->addSimulationResult(singleSimulationResultDTO);
	simulator->setSimulationResult(singleSimulationResultDTO);
	simulationCounter++;
	singleSimulationResultDTO = new SingleSimulationResultDTO();
	singleSimulationResultDTO->setID(simulationCounter);
}
	
void StatisticsSimulatorObserver::updateMultipleSimulations(){
	simulator->setSimulationResult(multipleSimulationResultDTO);
}

void StatisticsSimulatorObserver::reset(){
	multipleSimulationResultDTO = new MultipleSimulationResultDTO();
	singleSimulationResultDTO =new SingleSimulationResultDTO();
	stepResultDTO = new StepResultDTO();
	service1 = new ServiceInfoDTO();
	service2 = new ServiceInfoDTO();
	service3 = new ServiceInfoDTO();
	service4Coats = new ServiceInfoDTO();
	service4Pants = new ServiceInfoDTO();
	service4Suits = new ServiceInfoDTO();
	service5 = new ServiceInfoDTO();
	arrivals = new ArrivalsInfoDTO();
	exits = new ExitsInfoDTO();
	numberFlawedSuits = 0;
	numberNotFlawedSuits = 0;
	simulationCounter = 0;
	stepCounter = 0;
}

SingleSimulationResultDTO* StatisticsSimulatorObserver::getSingleSimulationResultDTO(){
	return singleSimulationResultDTO;
}

StepResultDTO* StatisticsSimulatorObserver::getStepResultDTO(){
	return stepResultDTO;
}

MultipleSimulationResultDTO* StatisticsSimulatorObserver::getMultipleSimulationResultDTO(){
	return multipleSimulationResultDTO;
}

StatisticsSimulatorObserver* StatisticsSimulatorObserver::instance() {
	if(!_instance)
	{
		_instance=new StatisticsSimulatorObserver();
	}
	return _instance;
}

