#pragma once
#include <cstdio>
#include <iostream>
#include <vector>
#include <map>
#include "uXgtcBurst.h"
#include "Sdu.h"
#include "AllocId.h"
#include "dXgtcFrame.h"
#include "hyra.h"
#include "maxmin.h"
#include "giant.h"
#include <fstream>
#include <sstream>
#include <string>

class Onu;

class Olt {	
public:
	enum
	{
		dbaStatik = 0,
		dbaHyra = 1,
		dbaMaxMin = 2,
		dbaGiant = 3
	};
	Olt::Olt();
	Olt::Olt(int dbaAlgoritmus, uint16_t pocetOnu, uint16_t pocetAllocId);

	uXgtcBurst getBuffer(int index);
	void addToBuffer(uXgtcBurst burst);
	std::vector<AllocStruc> Olt::dbaStatikGenerateBW(double &_cas, std::vector<Onu> &onus);
	void Olt::vygenerujStatistikyBwMap();

	Sdu getfirstBufferDown() { return BufferDown.front(); }
	void setBufferDown(Sdu _BufferDown) { BufferDown.push_back(_BufferDown); }
	
	void Olt::vygenerujStatistiky();
	float simuluj(double cas, int16_t aktualniStartTime, std::vector<Onu> *onus, uXgtcBurst PonUp[], DXgtcFrame &PonDown);


private:
	std::vector<uXgtcBurst> Buffer;
	std::map<int16_t, int16_t> Occ;
	std::vector<std::vector<Sdu>> BufferUp;
	std::vector<Sdu> BufferDown;
	std::int16_t poradiPoslednihoSdu;
	std::int16_t bitovaRychlost;	
	std::vector<double> casZahozeni;
	std::vector<double> casOdpovediSdu;
	std::vector<double> zpozdeniOdpovediSdu;
	std::int16_t velikostBufferu;	
	int odesilaDXgtc;
	DXgtcFrame odesilanyDXgtcRamec;
	std::vector<AllocStruc> bwMapa;
	int dbaAlgoritmus;
	Hyra hyra;
	std::vector<uint32_t> obsazenostFrontOnu;
	std::vector<Sdu> fragmentovaneSdu;
	std::vector<uint8_t> dbruOdeslano;
	Maxmin MaxMin;
	Giant giant;
	std::vector<std::map<double, uint16_t>> casGenerovaniGrantuStatik;
	uint16_t pocetAllocId;

};

class Onu {


public:
	Onu::Onu(int16_t _onuId, uint16_t pocetAllocId, uint16_t _bitovaRychlost);	
	AlokacniInterval Onu::generujIdleXgem(uint16_t velikost, DbrU _dbru);
	float simuluj(double cas, int16_t aktualniStartTime, uXgtcBurst PonUp[], DXgtcFrame* PonDown);

	void vygenerujStatistiky();

	uint16_t getBuffOcc() { return BuffOcc; }
	void setBuffOcc(uint16_t buffOcc) { BuffOcc = buffOcc; }

	int16_t getOnuId() { return OnuId; }
	void setOnuId(int16_t onuId) { OnuId = onuId; }

	std::vector<AllocId> getAllocIds() { return allocId; }
	void Onu::vygenerujStatistikyIdle();

private:
	uint16_t OnuId;		
	std::vector<AllocId> allocId;	
	uint16_t XgemPortId;
	uint16_t BuffOcc;
	std::vector<Sdu> BufferDown;
	double poradiPoslednihoSdu;
	uint16_t bitovaRychlost;	
	std::vector<double> casZahozeni;
	std::vector<double> casOdpovediSdu;
	std::vector<double> zpozdeniOdpovediSdu;
	uint16_t velikostBufferu;
	double casGenerovaniToku;
	uint32_t generujTokZa;
	int16_t velikostSDUProGenerovani;
	std::vector<std::map<double, uint16_t>> casGenerovaniIdle;
};