#ifndef CONTROLBANDIT_HPP
#define CONTROLBANDIT_HPP 

/* --- Include --- */
#include <mutex>
#include <vector>
#include <stdlib.h>

/* --- Define --- */
#define NB_FILL 4
#define NB_HEURISTIC 7
#define MT_EMA 0
#define MT_EPS 1
#define ALPHA_STEP 0.001
#define ALPHA_MIN 0.4
#define ALPHA_MAX 0.6
#define ALPHA_STATIC 0.5

/* --- Structure --- */
typedef struct {
	int fill;
	int heuristic;
}fillAndHeuristic;

class ControlBandit {
	public:
		ControlBandit();
		~ControlBandit();

		void setMethod(int, bool);
		void setEpsilon(double);

		bool queueIsEmpty();
		fillAndHeuristic next();

		void addFill(int, int);
		void addHeuristic(int, int);

	private:
		int method;
		int epsilon;
		std::mutex mutex;
		std::mutex mutexFill;
		std::mutex mutexHeuristic;
		std::vector<fillAndHeuristic> queue;
		bool alphaStatic;
		double alpha;
		double fema[NB_FILL];
		double hema[NB_HEURISTIC];

		fillAndHeuristic methodEma();
		fillAndHeuristic methodEps();

		int getBestFill();
		int getBestHeuristic();
		inline int getRandomFill() {return rand() % 4 + 2;}
		inline int getRandomHeuristic() {return rand() % 7;}

};

#endif