// ****************************************************************************
//
//          Aevol - An in silico experimental evolution platform
//
// ****************************************************************************
//
// Copyright: See the AUTHORS file provided with the package or <www.aevol.fr>
// Web: http://www.aevol.fr/
// E-mail: See <http://www.aevol.fr/contact/>
// Original Authors : Guillaume Beslon, Carole Knibbe, David Parsons
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
//
// ****************************************************************************


#ifndef AEVOL_PARAM_READER_H_
#define AEVOL_PARAM_READER_H_


// =================================================================
//                              Includes
// =================================================================
#include <cinttypes>
#include <cstdio>
#include <cstdlib>
#include <filesystem>
#include <fstream>
#include <memory>
#include <optional>
#include <string>
#include <vector>

#include "ParamValues.h"

namespace aevol {

class ParamReader {
 public :
  // =========================================================================
  //                          Constructors & Destructor
  // =========================================================================
  ParamReader() = delete; //< Default ctor
  ParamReader(const ParamReader&) = delete; //< Copy ctor
  ParamReader(ParamReader&&) = delete; //< Move ctor
  virtual ~ParamReader() = delete; //< Destructor

  // ==========================================================================
  //                                Operators
  // ==========================================================================
  ParamReader& operator=(const ParamReader& other) = delete;
  ParamReader& operator=(ParamReader&& other) = delete;

  // =========================================================================
  //                             Public Methods
  // =========================================================================
  static auto read_file(const std::filesystem::path& file_name) -> std::unique_ptr<ParamValues>;

  // =========================================================================
  //                                 Accessors
  // =========================================================================

 protected :
  // =========================================================================
  //                            Protected Methods
  // =========================================================================
  static void check_consistency(ParamValues& params);
  static auto line(std::ifstream& file, int32_t& cur_line) -> std::optional<std::vector<std::string>>;
  static auto format_line(const std::string&) -> std::optional<std::vector<std::string>>;
  static void interpret_line(const std::vector<std::string>& words,
                             int32_t cur_line,
                             const char* file_name,
                             ParamValues& values);
  static void nb_params_error(const std::string file_name,
                              int32_t line,
                              std::string option,
                              std::vector<std::string> usage,
                              std::vector<std::string> examples = {});
  static void stale_option_error(const std::string file_name,
                                 int32_t cur_line,
                                 const std::string option,
                                 const std::string comment = "");

  // =========================================================================
  //                               Data Members
  // =========================================================================
};

} // namespace aevol
#endif // AEVOL_PARAM_READER_H_
