#ifndef READING_MACHINE__H
#define READING_MACHINE__H

#include <filesystem>
#include <memory>
#include "Classifier.hpp"

class ReadingMachine
{
  public :

  static inline const std::string defaultMachineFilename = "machine.rm";
  static inline const std::string defaultModelFilename = "{}.pt";
  static inline const std::string lastModelFilename = "{}.last";

  private :

  std::string name;
  std::filesystem::path path;
  std::vector<std::unique_ptr<Classifier>> classifiers;
  std::map<std::string, int> state2classifier;
  std::vector<std::string> strategyDefinition;
  std::vector<std::vector<std::string>> classifierDefinitions;
  std::vector<std::string> classifierNames;
  std::set<std::string> predicted;
  bool train;

  std::unique_ptr<TransitionSet> splitWordTransitionSet{nullptr};

  private :

  void readFromFile(std::filesystem::path path);

  public :

  ReadingMachine(std::filesystem::path path, bool train);
  TransitionSet & getTransitionSet(const std::string & state);
  TransitionSet & getSplitWordTransitionSet();
  bool hasSplitWordTransitionSet() const;
  const std::vector<std::string> & getStrategyDefinition() const;
  Classifier * getClassifier(const std::string & state);
  bool isPredicted(const std::string & columnName) const;
  const std::set<std::string> & getPredicted() const;
  void trainMode(bool isTrainMode);
  void setDictsState(Dict::State state);
  void saveBest() const;
  void saveLast() const;
  void saveDicts() const;
  void setCountOcc(bool countOcc);
  void removeRareDictElements(float rarityThreshold);
  void resetClassifiers();
  void loadPretrainedClassifiers();
  int getNbParameters() const;
  void resetOptimizers();
};

#endif