#pragma once
#include "Heap.h"
#include "Coat.h"
#include "Pants.h"
#include "SimulatorSingleton.h"
#include "EvaluateFlaws.h"
#include "SuitFactory.h"
using namespace std;

class SuitProcessor
{
public:
	SuitProcessor()
	{
		Vector<Coat> aux1(10);
		coatStack = aux1;
		Vector<Pants> aux2(10);
		pantsStack = aux2;
		Vector<double> aux3(10);
		timeCoatStack = aux3;
		Vector<double> aux4(10);
		timePantsStack = aux4;
		pantsStackSize = 0;
		coatStackSize = 0;
	}

	static SuitProcessor* instance();

	void resetStacks()
	{
		Vector<Coat> aux1(10);
		coatStack = aux1;
		Vector<Pants> aux2(10);
		pantsStack = aux2;
		Vector<double> aux3(10);
		timeCoatStack = aux3;
		Vector<double> aux4(10);
		timePantsStack = aux4;
		pantsStackSize = 0;
		coatStackSize = 0;
	}

	int getPantsStackSize() {
		return pantsStackSize;
	}

	int getCoatStackSize() {
		return coatStackSize;
	}

	void addCoatToStack(Coat coat, double time)
	{
		SimulatorSingleton *sim = SimulatorSingleton::instance();
		SuitFactory *suitFactory = SuitFactory::instance();
		


		bool find = false;

		for(int register i=0; i<pantsStackSize; i++) {
			Pants pants = pantsStack[i];

			// verifica se existe um pants com o id do coat
			if (suitFactory->isSameSuit(coat, pants)) {
				pantsStackSize--;
				Vector<Pants> aux1(10);
				Vector<double> aux2(10);
				double timeEvent;

				// verifica qual dos objectos possui um tempo maior
				if (time < timePantsStack[i])
					timeEvent = timePantsStack[i];
				else
					timeEvent = time;

				// criar objecto Suit
				Suit suit = suitFactory->agregateSuit(coat, pants);
				suit.setInitialTime(pants.getInitialTime());
				EvaluateFlaws *evaluateFlaws;

				if (suit.isFlawed()){
					double timeServiceFlawed = sim->rStreamManager->rStream5->exponential(8);
					evaluateFlaws = new EvaluateFlaws(timeServiceFlawed +time);
					evaluateFlaws->suit = suit;
				} else {
					double timeServiceNotFlawed = sim->rStreamManager->rStream4->exponential(5);
					evaluateFlaws = new EvaluateFlaws(timeServiceNotFlawed +time);
					evaluateFlaws->suit = suit;
				}
				//coloca-lo na lista de eventos
				sim->add_event(evaluateFlaws);
				
				// elimina o elemento que se encontra no pantsStack[i]
				for(int register j=0; j<pantsStackSize; j++) {
					if (i != j) {
						aux1[j] = pantsStack[j];
						aux2[j] = timePantsStack[j];
					}
				}

				pantsStack = aux1;
				timePantsStack = aux2;
				find = true;
			}
		}

		if (find == false) {
			coatStack[coatStackSize] = coat;
			timeCoatStack[coatStackSize] = time;
			coatStackSize++;
		}

		/*cout << "addCoatToStack(Coat coat, double time)" << "\n";
		cout << "sizeCoatStack   " << coatStackSize << "\n";
		cout << "sizePantsStack   " << pantsStackSize << "\n";*/
	}

	void addPantsToStack(Pants pants, double time)
	{
		SimulatorSingleton *sim = SimulatorSingleton::instance();
		SuitFactory *suitFactory = SuitFactory::instance();
		bool find = false;

		for(int register i=0; i<coatStackSize; i++) {
			Coat coat = coatStack[i];

			// verifica se existe um pants com o id do coat
			if (suitFactory->isSameSuit(coat, pants)) {
				coatStackSize--;
				Vector<Coat> aux1(10);
				Vector<double> aux2(10);
				double timeEvent;

				// verifica qual dos objectos possui um tempo maior
				if (time < timeCoatStack[i])
					timeEvent = timeCoatStack[i];
				else
					timeEvent = time;

				// criar objecto Suit
				Suit suit = suitFactory->agregateSuit(coat, pants);
				suit.setInitialTime(pants.getInitialTime());
				EvaluateFlaws *evaluateFlaws;

				if (suit.isFlawed()){
					double timeServiceFlawed = sim->rStreamManager->rStream5->exponential(8);
					evaluateFlaws = new EvaluateFlaws(timeServiceFlawed +time);
					evaluateFlaws->suit = suit;
				} else {
					double timeServiceNotFlawed = sim->rStreamManager->rStream4->exponential(5);
					evaluateFlaws = new EvaluateFlaws(timeServiceNotFlawed +time);
					evaluateFlaws->suit = suit;
				}
				//coloca-lo na lista de eventos
				sim->add_event(evaluateFlaws);
				
				// elimina o elemento que se encontra no coatStack[i]
				for(int register j=0; j<coatStackSize; j++) {
					if (i != j) {
						aux1[j] = coatStack[j];
						aux2[j] = timeCoatStack[j];
					}
				}

				coatStack = aux1;
				timeCoatStack = aux2;
				find = true;
			}
		}

		if (find == false) {
			pantsStack[pantsStackSize] = pants;
			timePantsStack[pantsStackSize] = time;
			pantsStackSize++;
		}

		/*cout << "addPantsToStack(pants pants, double time)" << "\n";
		cout << "sizeCoatStack   " << coatStackSize << "\n";
		cout << "sizePantsStack   " << pantsStackSize << "\n";*/
	}
private:
	static SuitProcessor *_instance;
	Vector<Coat>coatStack;
	Vector<Pants>pantsStack;

	Vector<double>timeCoatStack;
	Vector<double>timePantsStack;

	int pantsStackSize;
	int coatStackSize;
};