#include "maxmin.h"

Maxmin::Maxmin(uint16_t &_pocetOnu, int16_t _pocetAllocId)
{
	std::map<double, uint16_t> statistikyGrantu;
	std::vector<uint16_t> vygenerovanyGrant;
	for (int i = 0; i < _pocetOnu*_pocetAllocId; i++) {
		vygenerovaneGranty.push_back(vygenerovanyGrant);
		casGenerovaniGrantuMaxMin.push_back(statistikyGrantu);
	}	
	pocetAllocId = _pocetAllocId;
	pocetOnu = _pocetOnu;
	fixedBw = 3;	
	assuredBW = 125;
}

std::vector<AllocStruc> Maxmin::generujBwmapu(double _cas, std::vector<uint32_t> _obsazenostFrontOnu, std::vector<uint8_t>* _dbruNastaveno) {
	std::vector<std::pair<uint32_t, uint16_t>> s;
	std::vector<uint32_t> obsazenostFrontOnu = _obsazenostFrontOnu;
	uint16_t nasledujiciStartTime = 0;
	uint16_t grantSize = 0;
	uint16_t pomocna = 0;
	uint16_t zpracovavanaObsazenostFronty = 0;
	uint16_t jizPridelenyAssuredBw = 0;
	uint8_t Flags = 1;
	std::vector<AllocStruc> bwMap;
	uint16_t volneBajty = 0;	
	std::vector<std::pair<uint32_t, uint16_t>> w;

	for (uint16_t i = 0; i < pocetOnu; i++) {
		for (uint16_t j = 0; j < pocetAllocId; j++) {
			if (j != 0) {
				if (_dbruNastaveno->at((i*pocetAllocId) + j))
				{
					uint16_t sumaPrechozichGrantu = 0;
					std::vector<uint16_t> zpracovavaneVygenerovanegranty = vygenerovaneGranty[(i*pocetAllocId) + j];
					for (uint16_t x = 0; x < zpracovavaneVygenerovanegranty.size(); x++)
					{
						sumaPrechozichGrantu += zpracovavaneVygenerovanegranty[x];
					}
					sumaPrechozichGrantu /= zpracovavaneVygenerovanegranty.size();
					s.push_back(std::make_pair(sumaPrechozichGrantu, (i*pocetAllocId) + j));
				}else
					s.push_back(std::make_pair(obsazenostFrontOnu[(i*pocetAllocId) + j] * 4, (i*pocetAllocId) + j));
				w.push_back(std::make_pair(0, (i*pocetAllocId) + j));
			}
		}
	}
	std::sort(s.begin(), s.end());
	
	uint16_t zpracovavanaFronta = 0;
	uint16_t sumaW = 0;
	while (s.size() > 0) {
		for (uint16_t i = 0; i < w.size(); i++) {
			sumaW += w[i].first;
		}
		volneBajty = ((38876-(fixedBw*4*pocetOnu)) - sumaW )/ s.size();
		if (volneBajty < 0)
			break;
		for (uint16_t i = 0; i < s.size(); i++) {
			zpracovavanaFronta = s[i].second;
			for (uint16_t x = 0; x < w.size(); x++)
			{
				if (w[x].second == zpracovavanaFronta)
				{
					if ((w[x].first + volneBajty) < s[i].first)
					{
						w[x].first += volneBajty;
					}
					else
					{
						w[x].first = s[i].first;
						s.erase(s.begin() + i);
						i--;
					}
				}
			}			
		}		
	}
	volneBajty = 9719 * 4;
	for(uint16_t i = 0; i<pocetOnu;i++){
			jizPridelenyAssuredBw = 0;			
			for (uint16_t j = 0; j < pocetAllocId; j++) {
				if (volneBajty <= 0)
				{
					Flags = 1;
					_dbruNastaveno->at((i*pocetAllocId) + j) = 1;
					AllocStruc aktualneGenerovanaStruktura = AllocStruc((i*pocetAllocId) + j, Flags, 0, 0);
					bwMap.push_back(aktualneGenerovanaStruktura);
					break;
				}
					
				zpracovavanaObsazenostFronty = _obsazenostFrontOnu[(i*pocetAllocId) + j];
				if (j == 0)
				{
					grantSize = fixedBw;
				}
				else if (j == 1) {
					for (uint16_t x = 0; x < w.size(); x++)
					{
						if (w[x].second == (i*pocetAllocId) + j) {
							grantSize = (w[x].first)/4;
						}if (grantSize == 0)
							grantSize = 1;
					}
				}
				else if (j == 2)
					grantSize = 1;
				else if (j == 3)
					grantSize = 1;

				if (grantSize > volneBajty/4)
					grantSize = volneBajty/4;
				
				Flags = 1;	
				_dbruNastaveno->at((i*pocetAllocId) + j) = 1;
				AllocStruc aktualneGenerovanaStruktura = AllocStruc((i*pocetAllocId)+j, Flags, nasledujiciStartTime, grantSize);
				bwMap.push_back(aktualneGenerovanaStruktura);
				nasledujiciStartTime += grantSize;
				Flags = 0;
				volneBajty -= grantSize*4;

				vygenerovaneGranty[(i*pocetAllocId) + j].push_back(grantSize);
				casGenerovaniGrantuMaxMin[(i*pocetAllocId) + j].insert(std::make_pair(_cas, grantSize));
				}			
	}
	return bwMap;
}

Maxmin::Maxmin() {

}


Maxmin::~Maxmin()
{
}

void Maxmin::vygenerujStatistikyBwMap() {
	for (uint16_t i=0; i < casGenerovaniGrantuMaxMin.size(); i++) {
		std::map<double, uint16_t>::iterator it = casGenerovaniGrantuMaxMin[i].begin();

		std::stringstream cestaSouboru;
		cestaSouboru << "BwMapProAllocId" << i << ".txt";		
		std::ofstream myfile;		
		myfile.open(cestaSouboru.str(), std::ofstream::out);
		if (myfile.is_open())
		{
			myfile << "casOdeslani granty\n";
			while (it != casGenerovaniGrantuMaxMin[i].end())
			{				

				myfile << it->first << " " << it->second << "\n";
				it++;
			}			
		}
		else std::cout << "Soubor nelze otevrit!";
		myfile.close();
	}	
}
