#ifndef DECODER__H
#define DECODER__H

#include <filesystem>
#include "ReadingMachine.hpp"
#include "SubConfig.hpp"

class Decoder
{
  private :

  ReadingMachine & machine;
  std::map<std::string, std::array<float,4>> evaluation;

  private :

  std::string getMetricOfColName(const std::string & colName) const;
  std::vector<std::pair<float,std::string>> getScores(const std::set<std::string> & colNames, float (Decoder::* metric2score)(const std::string &) const) const;
  float getMetricScore(const std::string & metric, std::size_t scoreIndex) const;
  float getPrecision(const std::string & metric) const;
  float getF1Score(const std::string & metric) const;
  float getRecall(const std::string & metric) const;
  float getAlignedAcc(const std::string & metric) const;

  public :

  Decoder(ReadingMachine & machine);
  void decode(BaseConfig & config, std::size_t beamSize, bool debug, bool printAdvancement);
  void evaluate(const Config & config, std::filesystem::path modelPath, const std::string goldTSV);
  std::vector<std::pair<float,std::string>> getF1Scores(const std::set<std::string> & colNames) const;
  std::vector<std::pair<float,std::string>> getAlignedAccs(const std::set<std::string> & colNames) const;
  std::vector<std::pair<float,std::string>> getRecalls(const std::set<std::string> & colNames) const;
  std::vector<std::pair<float,std::string>> getPrecisions(const std::set<std::string> & colNames) const;
};

#endif