
#ifndef score_h
#define score_h

#include <memory>
#include <list>
#include <map>

class Score {
private:
    std::vector<std::string> eid_vs_name;
    std::map<std::string, std::uint_fast64_t> name_vs_eid;
    std::map<std::string, double> name_vs_score;
public:
    Score(std::map<std::string, double>& scores) {
        name_vs_score.insert(scores.begin(), scores.end());
        std::list<std::string> ordered_by_score;
        eid_vs_name.assign(scores.size(), "");
        
        for (auto el : scores) {
            auto escore = el.second;
            auto ename = el.first;
            auto it = ordered_by_score.begin();
            for (; it != ordered_by_score.end(); ++it) {
                if (escore > name_vs_score.at(*it))
                    break;
            }
            ordered_by_score.insert(it, ename);
        }
        std::uint_fast64_t p = 0; // IMPORTANTE CHE INIZI DA 0
        for (auto e : ordered_by_score) {
            name_vs_eid[e] = p;
            eid_vs_name[p] = e;
            ++p;
        }
        return;
    }
    
    std::uint_fast64_t size() const {
        return name_vs_eid.size();
    }
    
    std::uint_fast64_t getEID(std::string name) const {
        if (name_vs_eid.find(name) == name_vs_eid.end()) {
            std::string err_str = "Score error getEID: " + name + ".";
            throw_line(err_str);
        }
        return name_vs_eid.at(name);
    }
    
    std::string getName(std::uint_fast64_t eid) const {
        if (eid_vs_name.size() >= eid) {
            std::string err_str = "Score error getName: " + std::to_string(eid) + ".";
            throw_line(err_str);
        }
        return eid_vs_name.at(eid);
    }
    
    double getScore(std::string name) const {
        if (name_vs_score.find(name) == name_vs_score.end()) {
            std::string err_str = "Score error getScore: " + name + ".";
            throw_line(err_str);
        }
        return name_vs_score.at(name);
    }
    
    double getScore(std::uint_fast64_t eid) const {
        if (name_vs_score.find(getName(eid)) == name_vs_score.end()) {
            std::string err_str = "Score error getScore: " + std::to_string(eid) + ".";
            throw_line(err_str);
        }
        return name_vs_score.at(getName(eid));
    }
};


#endif /* score_h */
