#ifndef QUEUE_H_
#define QUEUE_H_

#include <set>
#include "raw_address.h"
#include "util.h"
#include "queue.h"
#include <iostream>

/* 
 * Ceci est une simple file d'attente pour les requêtes de données qui partent
 * du processeur. 
 *
 * Les données sont supprimées de cette file dès qu'elles ont été chargées dans
 * le processeur. La taille de cette file est fixe. Si un élément est ajouté
 * alors qu'il dépasse la taille, il ne sera pas inséré.  Néanmoins, un message
 * devrait s'afficher sur la console.
 *
 * Le stockage interne est un arbre binaire rouge-noir qui permet insertion et
 * suppression en O(log n) de la STL.
 *
 * Note: si les élements stockés ne sont plus des entiers, il faudra
 * probablement ajouter une fonction pour comparer les elements afin que set
 * puisse les trier.
 */

template <typename T> 
class Queue {
    private:
        unsigned int max_size;
        std::set<T> elements;

    public:
        Queue(int max_size) {
            this->max_size = max_size;
        }

        void insert(T &element);
        void remove(T &element);
        bool is_full();
        bool is_empty();
        void print();
};

using namespace std;

template < typename T > void Queue<T>::insert(T &element) {
    if (elements.size() <= max_size) {    
        elements.insert(element);
    } else {
        std::cerr << "insertion ignored" << std::endl;
    }
}

template <typename T> bool Queue<T>::is_full() {
    return (elements.size() == max_size);
}

template < typename T >bool Queue<T>::is_empty() {
    return (elements.empty());
}

template < typename T > void Queue<T>::remove(T &element) {
    
    cout << "\t" << "QUEUE suppression de " << element <<  endl;

    if (elements.size() > 1) {
        typename std::set<T>::iterator it;
        it = elements.find(element);
        if (it != elements.end())
            elements.erase(it);
        else
            std::cerr << "removal ignored" << std::endl;
    }

//    if (elements.size() > 0) {
//        std::cout << "QUEUE : j'efface l'element : " << element << std::endl;
//        elements.erase(element);
//    } else {
//        std::cerr << "removal ignored" << std::endl;
//    }
}

template < typename T > void Queue<T>::print() {
    typename std::set<T>::iterator it;

    cout << "\t" << "QUEUE begin" << endl;
    for (it = elements.begin(); it != elements.end(); it++)
    {
        cout << "\t\t" << "element : " << *it << endl;
    }

    cout << "\t" << "QUEUE end" << endl;
}

#endif
